Angular - 测试组件 - 从 mock 返回 Promise.reject 时出错
Angular - Testing component - Error when returning Promise.reject from mock
我有一个组件单元测试,它没有按照我预期的方式处理来自模拟的承诺拒绝。
我在一个组件上有这个功能,它向 addUserToOrganisation
发送一些数据并处理 returns:
的 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
端点并且 return 是某种 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']);
}));
但是,我无法测试 'sad' 路径。我将模拟更改为 return a Promise.reject
,虽然我在 onSubmit
中有一个 .catch
,但我收到此错误:
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');
}));
有没有人有什么想法?
承诺拒绝应该被捕获,不处理它们将导致 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);
即使将来可能会处理拒绝,但实施方式无法 'know',因此承诺被视为未处理并触发 unhandledrejection
事件。
造成问题的是
tick();
fixture.detectChanges();
如果 tick()
存在 'just in case' 并且没有实际用途,那么它一开始就不应该存在。如果应该,则需要更改代码以不创建未处理的承诺:
mockUserService.addUserToOrganisation.and.callFake(() => Promise.reject('no'));
我有一个组件单元测试,它没有按照我预期的方式处理来自模拟的承诺拒绝。
我在一个组件上有这个功能,它向 addUserToOrganisation
发送一些数据并处理 returns:
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
端点并且 return 是某种 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']);
}));
但是,我无法测试 'sad' 路径。我将模拟更改为 return a Promise.reject
,虽然我在 onSubmit
中有一个 .catch
,但我收到此错误:
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');
}));
有没有人有什么想法?
承诺拒绝应该被捕获,不处理它们将导致 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);
即使将来可能会处理拒绝,但实施方式无法 'know',因此承诺被视为未处理并触发 unhandledrejection
事件。
造成问题的是
tick();
fixture.detectChanges();
如果 tick()
存在 'just in case' 并且没有实际用途,那么它一开始就不应该存在。如果应该,则需要更改代码以不创建未处理的承诺:
mockUserService.addUserToOrganisation.and.callFake(() => Promise.reject('no'));