为什么Angular中的Jasmine间谍功能没有被回调触发?

时间:2018-11-22 13:02:50

标签: angular typescript unit-testing callback jasmine

我要测试this.communication.subscribe()调用,该调用在参数中具有回调:

constructor (private communication: CommunicationProvider)

ngOnInit() {
    this.communication.subscribe(() => {
      this.router.navigate(["/success"]);
    });
  }

我已经使用callFake来模拟实现以调用callback()

beforeEach(async(() => {
    communicationSpy = jasmine.createSpyObj("CommunicationProvider", ["subscribe"]);
    routerSpy = jasmine.createSpyObj<Router>("Router", ["navigate"]);

    communicationSpy.subscribe.and.callFake((callback: any) => {
        callback();
    });
}));

it("should route on callback", (done: DoneFn) => {
    setTimeout(() => {
        expect(routerSpy.navigate).toHaveBeenCalledWith(["/success"]);
        done();
    }, 3000);
});

根据代码覆盖率结果,this.router.navigate(["/success"]);正在覆盖callback()。 但是"should route on callback"测试失败了,因为从未调用过routerSpy.navigate

为什么?

1 个答案:

答案 0 :(得分:0)

因为您永远不会触发订阅。

我不知道您的服务是什么,但是我们将利用您不使用限制运算符(例如taketakeUntil)的优势。

首先使用Subject将您的可观察对象模拟为热流:

component['communication'] = new Subject() as any;

现在,由于每个测试之前都有一个夹具createComponentInstance,因此您应该在每个测试中都有一个新的组件实例。这意味着您已经调用了ngOnInit并创建了订阅。

由于流很热,您可以在测试中订阅它:

it('should navigate', done => {
  component['communication'].subscribe(() => {
    expect(routerSpy.navigate).toHaveBeenCalledWith(["/success"]);
    done();
  });

  (component['communication'] as Subject).next(true);
});

通过next调用,您可以触发订阅,启动路由器并期望已被调用。

(PS:我已经使用数组语法和Subject来描述问题,可以随意使用想要触发订阅和模拟依赖项的任何方式)