Angular 10测试ViewContainerRef的注射器返回未定义 [英] Angular 10 testing ViewContainerRef's injector returns undefined
问题描述
问题从我们的项目从Angular 8.2.14迁移到Angular 10.2.24之后发生.
The problem happens after migrating our project from Angular 8.2.14 to Angular 10.2.24.
这是测试代码
fdescribe('PopupModalService Testing', () => {
let componentFactoryResolver: ComponentFactoryResolver;
let viewContainerRef: ViewContainerRef;
let popupModalService: PopupModalService;
beforeEach(waitForAsync(() => {
const viewContainerRefSpy = jasmine.createSpyObj('ViewContainerRef', ['insert']);
TestBed.configureTestingModule({
declarations: [
PopupModalComponent,
DialogApiComponent,
BrokerFormPopoverComponent,
BrokerContextMenuComponent
],
imports: [
ReactiveFormsModule,
TranslateModule.forRoot()
],
providers: [
{ provide: ViewContainerRef, useValue: viewContainerRefSpy },
PopupModalService
],
schemas: [
NO_ERRORS_SCHEMA
]
});
TestBed.overrideModule(BrowserDynamicTestingModule, {
set: {
entryComponents: [
PopupModalComponent,
DialogApiComponent,
BrokerFormPopoverComponent,
BrokerContextMenuComponent
]
}
});
componentFactoryResolver = TestBed.inject(ComponentFactoryResolver);
viewContainerRef = TestBed.inject(ViewContainerRef);
popupModalService = new PopupModalService(componentFactoryResolver);
}));
it('should create PopupModalComponent', () => {
expect(popupModalService.create(viewContainerRef, ModalType.SIMPLE, 'Test Title', 'Test Content', PopupActionType.SAVE)).toBeDefined();
});
it('should create BrokerContextMenuComponent', () => {
expect(popupModalService.createBrokerContextMenu(viewContainerRef, 999, 999)).toBeDefined();
});
});
这是组件的代码
@Injectable({
providedIn: 'root'
})
export class PopupModalService {
factoryResolver: ComponentFactoryResolver;
constructor(@Inject(ComponentFactoryResolver) factoryResolver) {
this.factoryResolver = factoryResolver;
}
create(
viewContainer: ViewContainerRef,
modalType: ModalType,
title: string,
content: string,
popupActionType?: PopupActionType): PopupModalComponent {
const factory = this.factoryResolver.resolveComponentFactory(PopupModalComponent);
const popupRef = factory.create(viewContainer.injector);
const popup = popupRef.instance;
popup.modalType = modalType;
popup.title = title;
popup.content = content;
popup.setComponentRef(popupRef);
popup.popupActionType = popupActionType;
popup.hide();
viewContainer.insert(popupRef.hostView);
popup.initFormValue();
return popup;
}
}
添加一些日志以查看哪个部分是undefined
之后,实际上是viewContainer.injector
是未定义的部分.
After adding some logs to see which part is undefined
, it's actually the viewContainer.injector
is the undefined one.
该代码过去确实有效,只是在迁移后无法运行.
This code did work in past, it only failed to run after the migration.
我尝试过
- Angular Directive ViewContainerRef测试模型.
- https://angular2.programmingpedia .net/zh/tutorial/831/dynamically-add-components-using-viewcontainerref-createcomponent
- Angular Directive ViewContainerRef Test Mock.
- https://angular2.programmingpedia.net/en/tutorial/831/dynamically-add-components-using-viewcontainerref-createcomponent
请帮助解决该问题.
推荐答案
我仍然找不到在Angular 10上不起作用的原因.但是,我的想法是将undefined
注入器替换为TestBed
本身就是Injector
.
I still can't find the reason one it doesn't work on Angular 10. However, my idea is to replace the undefined
injector by TestBed
. I've discovered that TestBed
is a Injector
itself.
在测试代码中,我将更改此行
In the test code, I will change this line from
expect(popupModalService.create(viewContainerRef, ModalType.SIMPLE, 'Test Title', 'Test Content', PopupActionType.SAVE)).toBeDefined();
到
expect(popupModalService.create(viewContainerRef, ModalType.SIMPLE, 'Test Title', 'Test Content', PopupActionType.SAVE, TestBed)).toBeDefined();
,然后在PopupModalService
中,将create
方法更改为
and in the PopupModalService
, change the create
method to
create(
viewContainer: ViewContainerRef,
modalType: ModalType,
title: string,
content: string,
popupActionType?: PopupActionType,
injector?: Injector): PopupModalComponent {
const factory = this.factoryResolver.resolveComponentFactory(PopupModalComponent);
const popupRef = factory.create(injector === undefined ? viewContainer.injector : injector);
const popup = popupRef.instance;
popup.modalType = modalType;
popup.title = title;
popup.content = content;
popup.setComponentRef(popupRef);
popup.popupActionType = popupActionType;
popup.hide();
viewContainer.insert(popupRef.hostView);
popup.initFormValue();
return popup;
}
我将最后一个参数injector
设为可选,这将使现有代码保持正常运行,而无需进行任何更改.
I make the last param injector
optional, this will keep the existing code work normally without any changes.
更新:更好的是,我们只能像这样更新测试代码
UPDATE: Better yet, we can update only the test code, like this
const viewContainerRefSpy = jasmine.createSpyObj('ViewContainerRef', ['insert'], {'injector': TestBed});
这与上面的工作原理相同,好处是我们不触摸普通代码,只更改测试代码.
This works the same as above, the benefit is we don't touch the normal code, we only change the test code.
这篇关于Angular 10测试ViewContainerRef的注射器返回未定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!