【问题标题】:How to unit test a call to a function called when subscribing to an ActivatedRoute data?如何对订阅 ActivatedRoute 数据时调用的函数的调用进行单元测试?
【发布时间】:2020-05-28 04:25:36
【问题描述】:

我想在我的 Angular 应用程序中对组件的 ngOnInit() 方法进行单元测试。 ngOnInit() 方法订阅 ActivatedRoute data 并调用 subscribe 方法内部的函数。下面是方法的代码:

component.ts

ngOnInit() {
  this.route.data.subscribe(data => this.store.patchState(data));
}

这是我的测试:

component.spec.ts

beforeEach(() => {
    fixture = TestBed.createComponent(xyzComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

it('#ngOnInit should call patchState', async(() => {

    const spy = spyOn(store, 'patchState');

    // When
    component.ngOnInit();

    fixture.detectChanges();

    // Then
    expect(spy.calls.count()).toBe(1, 'patchState has been called once.');

  }));

但是,当我运行测试时,我收到一条错误消息,告诉我“从未调用过预期的 spy patchState”。

我相信我的问题来自测试的异步性质,但我不知道为什么它不起作用。

我在这里做错了什么?

谢谢!

【问题讨论】:

    标签: angular unit-testing jasmine observable angular2-routing


    【解决方案1】:

    将订阅更改为:

    this.route.data.subscribe(data => {
                                       console.log('in route subscription);
                                       this.store.patchState(data)
                             });
    

    如果您没有看到console.log('in route subscription'),那么您可能没有正确地模拟activatedRoute

    试试这个:

    describe('xyzComponent', () => {
      let store: Store<...>; // for you to fill out
      let component: xyzComponent;
      let fixture: ComponentFixture<xyzComponent>;
      let data$ = new BehaviorSubject({ x: 1 }); // mock data for activatedRoute
    
      beforeEach(async() => {
        TestBed.configureTestingModule({
          imports: [ StoreModule.forRoot(....) ], // for you to fill out
          declarations: [ XYZComponent ],
          providers: [
            { provide: ActivatedRoute, useValue: { data: data$ } },
          ],
        }).compileComponents();
      });
    
      beforeEach(() => {
        store = TestBed.get(store);
        spyOn(store, 'patchState').and.callThrough(); // and.callThrough() is optional, do you want it to HAVE both a spy and call the actual implementation?
        fixture = TestBed.createComponent(xyzComponent);
        component = fixture.componentInstance;
        fixture.detectChanges(); // this fixture.detectChanges() will call `ngOnInit` for us, so we don't have to manually call it
      });
    
      it('ngOnInit should call patchState', () => {
        expect(store.patchState).toHaveBeenCalledWith({ x: 1 });
      });
    });
    

    这应该有望让您畅通无阻。您还可以在以后的测试中更改route.data,并通过将data.next$({....}) 设置为您的未来值来查看它的反应。

    【讨论】:

    • 非常感谢您花时间研究并回答,问题确实来自模拟的激活路由!再次感谢,问候!
    猜你喜欢
    • 2021-06-28
    • 1970-01-01
    • 2017-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多