首页 > 解决方案 > 如何触发订阅函数内的事件发射器。角度单元测试

问题描述

我一直在尝试测试一个包含 EventEmitter 订阅的函数,单元测试正在调用订阅,但是无法测试订阅中的代码,我的意思是,filter即使getDocuments()订阅也没有被测试正在被调用。

  describe('trigger_data test', () => {
    it('not filter in storage', async(() => {
      component.filter = null;
      spyOn(component, 'getDocuments');
      spyOn(mockSharedService.trigger_data, 'subscribe').and.returnValue(of(true));
      component.triggerData();
      expect(mockSharedService.trigger_data.subscribe).toHaveBeenCalled();
      expect(component.filter).toEqual(1); //Error: Expected null to equal 1.
      expect(component.getDocuments).toHaveBeenCalled(); //Error: Expected spy getDocuments to have been called.
    }));
  });

这是功能

  triggerData() {
    this.sharedService.trigger_data.subscribe(() => {
      if (sessionStorage.getItem('filter_pp') !== null) {
        this.filter = Number(sessionStorage.getItem('filter_pp'));
      } else {
        this.filter = 1;
      }
      this.getDocuments();
    });
  }

当另一个组件发出布尔值时,订阅会触发代码。

标签: angularunit-testingangular7karma-jasmine

解决方案


您正在监视该subscribe方法并让它返回一个 Observable,这是不正确的。(subscribe 是 Observable 上的一个方法,它返回一个订阅)

有几种方法可以解决此问题:

  • 确保在创建模拟时将 mockSharedService.trigger_data 设置为正确的 Observable(为此,我认为我们需要查看更多测试代码)。
  • 在您的测试中使用以下命令覆盖 mockSharedService.trigger_data:(mockSharedService.trigger_data = of(true)注意:如果 trigger_data 是 EventEmitter,TypeScript 不会喜欢这样,您可能需要mockSharedService.trigger_data = of(true) as any:)
  • 如果您想避免转换为任何类型,就像我在前面的示例中所做的那样,您可以使用:
  const emitter = new EventEmitter();
  mockSharedService.trigger_data = emitter;
  emitter.emit(true);
  • 使 trigger_data 成为返回 Observable 的方法,并使用spyOn(mockSharedService, 'trigger_data').and.returnValue(of(true)). 但是,这样做还需要您将triggerData实现更改为调用trigger_data(),而不仅仅是将其作为属性访问。

我一直在尝试测试一个包含 EventEmitter 订阅的函数

此外,您可能希望使用 Subject 而不是 EventEmitter,Angular 使用 EventEmitter 进行输出绑定。在实现自己时,在 Angular 的输出之外,我们可以使用 Subjects 而不是 EventEmitters(它实际上扩展了 Subjects,为了 Angular 的输出。参见:https ://github.com/angular/angular/blob/master/packages/核心/src/event_emitter.ts#L64 )


推荐阅读