Angular 2:如何在单元测试时模拟ChangeDetectorRef
问题描述:
我刚刚开始使用Unit-Testing,并且我已经能够模拟我自己的服务以及一些Angular和Ionic,但是不管我做什么ChangeDetectorRef
保留相同。Angular 2:如何在单元测试时模拟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, useClass: ChangeDetectorRefMock},
]
}
})
.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块组件,所以它是因为它是在文档here进行规范之间复位:
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中,因此它是可访问的。
,如果你想在运行时为您的测试访问私有属性这样,它是给你。我个人并没有任何问题,我按照我的规格做了更多的报道。
的ChangeDetectorRef由角2编译器给予特殊待遇。我认为你不能提供它。您可以AsyncPipe https://github.com/angular/angular/blob/8f5dd1f11e6ca1888fdbd3231c06d6df00aba5cc/modules/%40angular/common/test/pipes/async_pipe_spec.ts有用于SpyChangeDetectorRef – yurzui
我打同样的问题,检查测试 - 如何有人在为此工作吗? – SamF