Search code examples
angularunit-testingjasminerxjsthrow

Angular/RxJS 6 - How to unit-test that instructions triggered by a next() throw an exception


Before migrating to RxJs6, one of my unit tests was :

it('should do what I expect, () => {
  expect(() => {
    myComponent.mySubject.next({message: 'invalid'});
  }).toThrow('invalid is not an accepted message');
})

In my component, I subscribe to the subject and call a private method that can throw an exception. Something looking like that :

export class MyComponent {
  //...
  mySubject = new Subject();
  //...
  ngOnInit(){
    this.mySubject.subscribe(obj => this._doSomething(obj))
  }
  //...
  private _doSomething(obj) {
    if ('invalid' === obj.message) {
      throw new Error('invalid is not an accepted message');
    }
    //...
  }
}

Since I migrated to RxJs6 this UT does not work anymore (it worked before) and I cannot figure out how to make it work.

I read the migration guide, especially this section : Replacing synchronous error handling, but it is about subscribe(), not next()...

Thanks in advance


Solution

  • I found a workaround.

    Not sure about the relevance, but it seems to work for me.

    I use the angular testing methods fakeAsync and tick to trigg the emission of the unhandled exception.

    Transform :

    it('should do what I expect, () => {
      expect(() => {
        myComponent.mySubject.next({message: 'invalid'});
      }).toThrow('invalid is not an accepted message');
    })
    

    into :

    it('should do what I expect, fakeAsync(() => {
      myComponent.mySubject.next({message: 'invalid'});
      expect(() => tick())
        .toThrow('invalid is not an accepted message');
    }))
    

    By the way, this trick also makes me sure that if the exception is not thrown, the test will fail.