【问题标题】:How to mock the Event Emitter of a Service in Jasmine/Angular如何在 Jasmine/Angular 中模拟服务的事件发射器
【发布时间】:2020-12-07 11:34:00
【问题描述】:

我正在尝试为具有包含 EventEmitter 的依赖服务的组件编写单元测试。 我已经在这个组件中订阅了这个事件发射器。 我怎样才能模拟这个?

依赖服务:

Service A {
  testEmitter : EventEmitter<any>();
}

组件有功能:

funcA() {
  service.testEmitter.subscribe()....//
}

如何模拟此订阅?该函数在初始化过程中被调用,所以测试不起作用

【问题讨论】:

  • “初始化”是什么?是constructor 还是ngOnInit
  • @Buczkowski 它是 ngOnInit。这只是告诉我的测试不会运行,除非我解决这个问题

标签: angular unit-testing mocking jasmine


【解决方案1】:
@Injectable()
class SomeService {
  testEmitter = new EventEmitter<any>();
}

@Component({
  selector: 'app-some',
  template: ''
})
class SomeComponent implements OnInit {
  shouldCall = true;

  constructor(private someService: SomeService) {
  }

  ngOnInit() {
    if (this.shouldCall) {
      this.funcA();
    }
  }

  private funcA() {
    this.someService.testEmitter.subscribe();
  }
}

describe('SomeComponent', () => {
  let component: SomeComponent;
  let fixture: ComponentFixture<SomeComponent>;
  let someServiceMock;

  beforeEach(async(() => {
    someServiceMock = {testEmitter: {subscribe: createSpy('testEmitter subscribe')}};

    TestBed.configureTestingModule({
      declarations: [SomeComponent],
      providers: [{provide: SomeService, useValue: someServiceMock}]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(SomeComponent);
    component = fixture.componentInstance;
    // fixture.detectChanges(); // move to test suites as it cause ngOnInit call
  });

  it('should subscribe', () => {
    fixture.detectChanges();

    expect(someServiceMock.testEmitter.subscribe).toHaveBeenCalled();
  });

  it('should not subscribe', () => {
    component.shouldCall = false;

    fixture.detectChanges();

    expect(someServiceMock.testEmitter.subscribe).toHaveBeenCalled();
  });
});

【讨论】:

    【解决方案2】:

    首先,在服务中使用EventEmitter是错误的。

    它仅供组件使用!

    我犯了同样的错误,并且在测试中也遇到了问题。无论如何,对于当前的情况,您可以使用 rxjs 'Subject' 来模拟 Emitter 行为

    describe('SomeComponent', () => {
      let component: SomeComponent;
      let fixture: ComponentFixture<SomeComponent>;
    
       let aServiceInj: ServiceA;
       const aServiceMock = {
          testEmitter: new Subject<any>();
          triggerEmitter(res) {
            this.testEmitter.next(res);
          }
        };
    
      beforeEach(async(() => {
    
        await TestBed.configureTestingModule({
          declarations: [SomeComponent],
          providers: [{provide: ServiceA, useValue: aServiceMock}]
        }).compileComponents();
      }));
    
      beforeEach(() => {
        fixture = TestBed.createComponent(SomeComponent);
        component = fixture.componentInstance;
        aServiceInj = TestBed.inject(ServiceA);
        fixture.detectChanges();
      });
    
      it('should trigger service emit', () => {
    
        aServiceInj.triggerEmitter({prop: 'whatever you want'});
    
       // ...Handle service respond here and write tests
      });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 2014-11-22
      • 1970-01-01
      相关资源
      最近更新 更多