Angular 2:如何在单元测试时模拟ChangeDetectorRef

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(); 
} 
} 

我已经尝试了一切,asyncfakeAsyncinjector([ChangeDetectorRef],() => {})

没有用。

+0

的ChangeDetectorRef由角2编译器给予特殊待遇。我认为你不能提供它。您可以AsyncPipe https://github.com/angular/angular/blob/8f5dd1f11e6ca1888fdbd3231c06d6df00aba5cc/modules/%40angular/common/test/pipes/async_pipe_spec.ts有用于SpyChangeDetectorRef – yurzui

+0

我打同样的问题,检查测试 - 如何有人在为此工作吗? – SamF

万一有人运行到这一点,这是为我工作很好的一种方法:

当你在注入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中,因此它是可访问的。

,如果你想在运行时为您的测试访问私有属性这样,它是给你。我个人并没有任何问题,我按照我的规格做了更多的报道。