Figure out rxjs marble tests in Angular

129 views Asked by At

I would like to test a service with the help of marble tests.

The basic service looks like this:

interface User {
  name: string;
}

@Injectable({
  providedIn: 'root',
})
export class ServiceToTest {
  public get user$(): Observable<User | undefined> {
    return this._user$.asObservable();
  }

  public get initials$(): Observable<string> {
    return this.user$.pipe(map((user) => this._getUserInitials(user)));
  }

  private readonly _user$: ReplaySubject<User | undefined>;

  constructor() {
    this._user$ = new ReplaySubject<User | undefined>(1);
  }

  public setUser(user: User | undefined) {
    this._user$.next(user);
  }

  private _getUserInitials(user: User | undefined) {
    const initialArray = user?.name?.split(' ');

    if (!initialArray?.length) {
      return '';
    }

    return `${initialArray[0][0]}${initialArray[initialArray?.length - 1][0]}`;
  }
}

But I can not figure out, how to implement a unit test with marble testing of the observables.

I tried to get this test setup working

describe('ServiceToTest ', () => {
  let service: ServiceToTest ;
  let testScheduler: TestScheduler;

  beforeEach(() => {
    service = new ServiceToTest();
    testScheduler = new TestScheduler((actual, expected) => {
      expect(actual).toEqual(expected);
    });
  });

  it('should get the correct user', () => {
    testScheduler.run((helpers) => {
      const testUser: User = { name: 'SERVICE TEST'};
      const { cold, expectObservable } = helpers;
      const users = cold('ab|', { a: undefined, b: testUser });
      service.setUser(testUser);
      const expected = '(ab|)';
      expectObservable(service.user$).toBe(expected, { a: undefined, b: testUser });
  });
});

But it fails.

As I want to develop my understanding of observables and marble testing, I thought this might be an simple first attempt. Somehow I am running into a wall and do not know how to continue. Maybe somebody could help me get it working.

1

There are 1 answers

0
Alex Janßen On

I got a working solution:

  it('should get the correct user', () => {
testScheduler.run((helpers) => {
  const { cold, expectObservable } = helpers;
  const testUser: User = { name: 'SERVICE TEST', authenticated: false };
  const users = 'a-b-a';
  const expected = 'a-b-a';

  spyOn(userService['_user$'], 'asObservable').and.returnValue(
    cold(users, {
      a: undefined,
      b: testUser,
    })
  );

  expectObservable(userService.user$).toBe(expected, {
    a: undefined,
    b: testUser,
  });
});

});