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
That's correct. In RxJS 5 when subscribing with subscribe
if you didn't set any error
handler the error was just re-thrown. That's why your unit test worked before.
But that's not how it works in RxJS 6 because all non-handled errors are re-thrown in window.onerror
or process.on('error')
(depending on your environment).
What you could do is making the test async and then checking that one of the handlers above was called:
it('should do what I expect, done => {
process.once('error', () => done());
myComponent.mySubject.next({message: 'invalid'});
});
This is mocha
style but I guess in Jasmine it's going to be similar.
Actually, what you have is not a very good way to test observable chains because whether an error is handled or not is only subscribers business and not caller's. In other words, you shouldn't test how an emission is handled by subscribers.
It took me a while to find the appropriate commit but read the description here https://github.com/ReactiveX/rxjs/commit/cd9626a4f93cac6f631d5a97dd9c9b2aa8e4b5db (it's mentioned also in the CHANGELOG.md
).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With