angularjasminekarma-jasmineangular-unit-testangular-event-emitter

How to test custom event emitter service in Angular 12


I have implement component communication using emit emitter service.

service.ts

import { EventEmitter, Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class BroadcastService {

  updateDetails = new EventEmitter();

  constructor() { }
}

i am emitting an event from component 1 using

this.broadcastService.updateDetails.emit();

and i'm subscribing to that event in component 2 as follows

this.broadcastService.updateDetails.subscribe(() => {
// code to executed after receiving the event
});

Now my question is

when i am writing unit test cases for component 2, how should i mock the 'broadcastService.updateDetails' so that subscribe method is called and the code inside the subscribe() should be covered in code coverage.


Solution

  • In jasmine karma tests you will need to spy on the updateDetails.emit function and mock the returned value with the .and.returnValue() method.

    Let's assume the subscribing to the event in your component 2 looks like this:

    // component2.ts
    updateDetailsInComponent2() {
      this.broadcastService.updateDetails.subscribe(() => {
      // code to executed after receiving the event
      });
    }
    

    So a unittest for the updateDetails function could look like this.

    // component2.spec.ts
    describe('Component2', () => {
      let component2: Component2;
      let fixture: ComponentFixture<Component2>;
      let service: BroadCastService;
    
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [ Component2 ]
        })
        .compileComponents();
    
        fixture = TestBed.createComponent(HomePageComponent);
        component = fixture.componentInstance;
        service = Testbed.inject(BroadCastService);
        fixture.detectChanges();
      });
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    
      it('updateDetails test', () => {
        // create an eventMock which is returned in the mock
        const eventMock = new Event()
        spyOn(service.updateDetails, 'emit').mockReturnValue(eventMock);
        component2.updateDetailsInComponent2();
        fixture.detectChanges();
        expect(service.updateDetails.emit).toHaveBeenCalled();
      });
    

    the important part is that you actually create a correct eventMock which is returned in the and.returnValue(eventMock) part of the spy.