21. Test an effect

In this section we will use marble tests to test our effects observable streams.

1. Fix broken EventComponent test

  • Add the dispatch method to our fake Store provided.

src/app/event/containers/event/event.component.spec.ts
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { EventComponent } from './event.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { EventService } from '../../services/event.service';
import { Store } from '@ngrx/store';

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        {
          provide: EventService,
          useValue: {
            getAttendees: () => {},
          }
        },
        {
          provide: Store,
          useValue: {
            pipe: () => {},
            dispatch: () => {}
          }
        }
      ],
      declarations: [EventComponent],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  }));

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

2. Install jest-marbles

npm i jest-marbles@latest -D

3. Add effect spec file

  • Add attendees.effects.spec.ts file.

Unknown why toBeObservable Matcher not working with jest?

src/app/event/state/attendees/attendees.effects.spec.ts
import { TestBed } from '@angular/core/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { hot, cold } from 'jest-marbles';
import { of, Observable } from 'rxjs';

import { AttendeesEffects } from './attendees.effects';
import {
  LoadAttendees,
  LoadAttendeesSuccess,
  AttendeesActions
} from './attendees.actions';
import { Attendee } from '../../../models';
import { EventService } from '../../services/event.service';

describe(`Effect: Attendess`, () => {
  let actions: Observable<AttendeesActions>;
  let effects: AttendeesEffects;
  let service: EventService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [],
      providers: [
        AttendeesEffects,
        provideMockActions(() => actions),
        {
          provide: EventService,
          useValue: {
            getAttendees: jest.fn()
          }
        }
      ]
    });

    service = TestBed.get(EventService);
    effects = TestBed.get(AttendeesEffects);
  });

  it('should return a cold Observable of LoadAttendeesSuccess action', () => {
    const fakeAttendees = [
      { name: 'Duncan', attending: false, guests: 0 } as Attendee
    ];
    const action = new LoadAttendees();
    const completion = new LoadAttendeesSuccess(fakeAttendees);

    jest
      .spyOn(service, 'getAttendees')
      .mockImplementation(() => of(fakeAttendees));

    actions = hot('--a-', { a: action });
    const expected = cold('--(b)', { b: completion });
    expect(effects.getAttendees$).toBeObservable(expected);
  });
});
Web Link: Link to the demo app running in StackBlitz

Extras and Homework

Read more about testing observables

Last updated