在迁移到 RxJs6 之前,我的一个单元测试是:
it('should do what I expect, () => {
expect(() => {
myComponent.mySubject.next({message: 'invalid'});
}).toThrow('invalid is not an accepted message');
})
在我的组件中,我订阅了主题并调用了一个可以引发异常的私有方法。看起来像这样的东西:
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');
}
//...
}
}
自从我迁移到 RxJs6 以来,这个 UT 不再工作(它以前工作过(,我不知道如何让它工作。
我阅读了迁移指南,尤其是本节:替换同步错误处理,但它是关于subscribe()
,而不是next()
......
提前致谢
没错。在 RxJS 5 中,当您使用subscribe
订阅时,如果您没有设置任何error
处理程序,则只会重新抛出错误。这就是你的单元测试以前工作的原因。
但这不是它在 RxJS 6 中的工作方式,因为所有未处理的错误都会在window.onerror
或process.on('error')
中重新抛出(取决于您的环境(。
您可以做的是使测试异步,然后检查是否调用了上述处理程序之一:
it('should do what I expect, done => {
process.once('error', () => done());
myComponent.mySubject.next({message: 'invalid'});
});
这是mocha
风格,但我想在茉莉花中它会很相似。
实际上,您拥有的并不是测试可观察链的好方法,因为是否处理错误只是订阅者的业务,而不是调用者的业务。换句话说,您不应该测试订阅者如何处理排放。
我花了一段时间才找到合适的提交,但 https://github.com/ReactiveX/rxjs/commit/cd9626a4f93cac6f631d5a97dd9c9b2aa8e4b5db 阅读了这里的描述(CHANGELOG.md
中也提到了(。
我找到了解决方法。
不确定相关性,但它似乎对我有用。
我使用角度测试方法fakeAsync
和tick
来触发未处理异常的发射。
变换:
it('should do what I expect, () => {
expect(() => {
myComponent.mySubject.next({message: 'invalid'});
}).toThrow('invalid is not an accepted message');
})
到:
it('should do what I expect, fakeAsync(() => {
myComponent.mySubject.next({message: 'invalid'});
expect(() => tick())
.toThrow('invalid is not an accepted message');
}))
顺便说一句,这个技巧也让我确信,如果不抛出异常,测试就会失败。