我有一个组件单元测试,它没有像我预期的那样处理模拟的承诺拒绝。
我在一个组件上有这个函数,它将一些数据发送到addUserToOrganisation
并处理它返回的Promise:
public onSubmit() {
this.saveStatus = 'Saving';
this.user = this.prepareSaveUser();
this._userService.addUserToOrganisation(this.user)
.then(() => this._router.navigate(['/profile']))
.catch(error => this.reportError(error));
}
在测试这个组件时,我为UserService
提供了一个模拟器,它监视addUserToOrganisation
端点并返回某种类型的Promise:
mockUserService = jasmine.createSpyObj('mockUserService', ['getOrgId', 'addUserToOrganisation']);
mockUserService.getOrgId.and.returnValue(Promise.resolve('an id'));
mockUserService.addUserToOrganisation.and.returnValue(Promise.resolve());
这适用于快乐路径(解决) - 我可以测试this._router.navigate()
被调用等等。以下是这条快乐路径的通过测试:
it('should navigate to /profile if save is successful', fakeAsync(() => {
fixture.detectChanges();
tick();
fixture.detectChanges();
component.userForm.controls['firstName'].setValue('John');
component.userForm.controls['lastName'].setValue('Doe');
component.userForm.controls['email'].setValue('j.d@gmail.com');
component.onSubmit();
tick();
fixture.detectChanges();
expect(mockRouter.navigate).toHaveBeenCalledWith(['/profile']);
}));
然而,我在测试“悲伤”时遇到了麻烦。路径。我改变我的模拟以返回Promise.reject
,虽然.catch
中有onSubmit
,但我收到此错误:
Error: Uncaught (in promise): no
这令人困惑。这是我对这条悲伤道路的考验。请注意,我更改了模拟调用的响应。
it('should show Failed save status if the save function fails', fakeAsync(() => {
mockUserService.addUserToOrganisation.and.returnValue(Promise.reject('no'));
fixture.detectChanges();
tick();
fixture.detectChanges();
component.userForm.controls['firstName'].setValue('John');
component.userForm.controls['lastName'].setValue('Doe');
component.userForm.controls['email'].setValue('j.d@gmail.com');
component.onSubmit();
tick();
fixture.detectChanges();
expect(component.saveStatus).toEqual('Failed! no');
}));
有没有人有任何想法?
答案 0 :(得分:2)
应该捕获Promise拒绝,如果未处理它们将导致Zone.js承诺实现(在Angular应用程序中使用)和其他一些(Chrome,core-js承诺polyfill等)中出错。
应该同步捕获拒绝以便被视为处理。这样可以保证始终处理错误。
这是处理承诺:
const p = Promise.reject();
p.catch(err => console.error(err));
这是未经处理的承诺:
const p = Promise.reject();
setTimeout(() => {
p.catch(err => console.error(err));
}, 1000);
即使将来可能会处理拒绝,但实施方式也无法知道'关于这一点,所以承诺被认为是未处理的,并且unhandledrejection
事件被触发。
造成问题的是
tick();
fixture.detectChanges();
如果tick()
存在,则只是以防万一'并且没有真正使用它,它首先不应该存在。如果它应该然后代码需要更改为不创建未处理的承诺:
mockUserService.addUserToOrganisation.and.callFake(() => Promise.reject('no'));