我刚刚开始使用Unit-Testing,我已经能够模拟自己的服务以及一些Angular和Ionic,但无论我做什么,ChangeDetectorRef保持不变.
我的意思是这是什么样的巫术?
beforeEach(async(() => TestBed.configureTestingModule({ declarations: [MyComponent],providers: [ Form,DomController,ToastController,AlertController,PopoverController,{provide: Platform,useClass: PlatformMock},{ provide: NavParams,useValue: new NavParams({data: new PageData().Data}) },{provide: ChangeDetectorRef,useClass: ChangeDetectorRefMock} ],imports: [ FormsModule,ReactiveFormsModule,IonicModule ],}) .overrideComponent(MyComponent,{ set: { providers: [ {provide: ChangeDetectorRef,useClass: ChangeDetectorRefMock},],viewProviders: [ {provide: ChangeDetectorRef,] } }) .compileComponents() .then(() => { let fixture = TestBed.createComponent(MyComponent); let cmp = fixture.debugElement.componentInstance; let cdRef = fixture.debugElement.injector.get(ChangeDetectorRef); console.log(cdRef); // logs ChangeDetectorRefMock console.log(cmp.cdRef); // logs ChangeDetectorRef,why ?? }) ));
it('fails no matter what',async(() => { spyOn(cdRef,'markForCheck'); spyOn(cmp.cdRef,'markForCheck'); cmp.ngOnInit(); expect(cdRef.markForCheck).toHaveBeenCalled(); // fail,why ?? expect(cmp.cdRef.markForCheck).toHaveBeenCalled(); // success console.log(cdRef); // logs ChangeDetectorRefMock console.log(cmp.cdRef); // logs ChangeDetectorRef,why ?? }));
@Component({ ... }) export class MyComponent { constructor(private cdRef: ChangeDetectorRef){} ngOnInit() { // do something this.cdRef.markForCheck(); } }
我已经尝试了所有东西,async,fakeAsync,injector([ChangeDetectorRef],()=> {}).
什么都行不通.
万一有人碰到这个,这是一种对我有用的方法:
当您在构造函数中注入ChangeDetectorRef实例时:
constructor(private cdRef: ChangeDetectorRef) { }
您将cdRef作为组件上的私有属性之一,这意味着您可以监视组件,存根该属性并让它返回您想要的任何内容.此外,您可以根据需要断言其调用和参数.
在您的spec文件中,调用您的TestBed而不提供ChangeDetectorRef,因为它不会提供您提供的内容.设置相同beforeEach块的组件,因此它在规范之间重置,因为它在文档@L_404_0@中完成:
component = fixture.componentInstance;
然后在测试中,直接监视属性
describe('someMethod()',() => { it('calls detect changes',() => { const spy = spyOn((component as any).cdRef,'detectChanges'); component.someMethod(); expect(spy).toHaveBeenCalled(); }); });
有了间谍,你可以使用.and.returnValue()并让它返回你需要的任何东西.
请注意,(component as any)用作cdRef是私有属性.但私有在实际编译的JavaScript中不存在,因此可以访问.
如果您希望在运行时以这种方式访问测试的私有属性,则由您决定.我个人对它没有任何问题,我按照我的规格来做更多的报道.