【问题标题】:Angular - mock Promise method for Jasmine unit testAngular - Jasmine 单元测试的模拟 Promise 方法
【发布时间】:2018-07-27 14:42:39
【问题描述】:

测试方法

  public onSubmit(registerData: RegisterDataModel): void {
    this.registrationService.registerWithEmailAndPassword(registerData).then((msg: string[]) =>
      this.router.navigate(['/completeSignUp']).then(() => {
        msg.forEach(singleMessage => this.notificationService.primary(singleMessage));
      }))
      .catch((msg) => msg.forEach(singleMessage => {
        this.notificationService.danger(singleMessage);
      }));
  }

我想测试我的方法中是否调用了router.navigate。现在我想模拟我的service.registerWithEmailAndPasswort Promise 但不知何故我无法模拟它。

我的规格文件

//Stubs
const routerStub: Router = jasmine.createSpyObj('Router', ['navigate']);
const registryStub: RegistrationService = jasmine.createSpyObj('RegistrationService', ['registerWithEmailAndPassword']);

单元测试

  it('should navigate on promise - success', () => {
    (<jasmine.Spy>registryStub.registerWithEmailAndPassword).and.callThrough();
    const spy = (<jasmine.Spy>routerStub.navigate);
    component.onSubmit({username: null, email: null, password: null, passwordConfirm: null, termsAndCondition: null});
    expect(spy).toHaveBeenCalledWith(['/completeSignUp']);
  });

出现的错误是:TypeError: Cannot read property 'then' of undefined 有人如何正确模拟这项服务吗?

编辑

我也尝试过模拟这样的承诺:

    (<jasmine.Spy>registryStub.registerWithEmailAndPassword)
  .and.returnValue(new Promise(() => Promise.resolve()));

但它仍然让我失望:

Expected spy Router.navigate to have been called with [ [ '/completeSignUp' ] ] but it was never called.

【问题讨论】:

    标签: angular unit-testing jasmine mocking karma-jasmine


    【解决方案1】:

    正如 Silicon Soul 提到的,您绝对需要使用返回值模拟 router.navigate 承诺,否则它将进入 Promise.reject()。通过添加(&lt;jasmine.Spy&gt;routerStub.navigate).and.returnValue(Promise.resolve()); 单元测试应该没问题。 最终的单元测试应该如下所示:

      it('should navigate on promise - success', fakeAsync(() => {
        const spy = (<jasmine.Spy>routerStub.navigate).and.returnValue(Promise.resolve());
        (<jasmine.Spy>registryStub.registerWithEmailAndPassword).and.returnValue(Promise.resolve(['test']));
        component.onSubmit({username: 'test', email: 'test', password: 'test', passwordConfirm: 'test', termsAndCondition: true});
    
        tick();
        expect(spy).toHaveBeenCalledWith(['/completeSignUp']);
      }));
    

    【讨论】:

      【解决方案2】:

      您将收到错误,因为 registerWithEmailAndPassword 间谍没有返回 Promise。你可以使用 callFake 来返回一个 Promise:

      (<jasmine.Spy>registryStub.registerWithEmailAndPassword).and.callFake(() => Promise.resolve([]));
      

      此外,Promise 是异步的,因此您可能应该使用 fakeAsync 测试并勾选,或者超时或使用 then 方法返回一个对象,而不是 Promise。

      【讨论】:

      • 首先感谢您的回复,但是 registerWithEmailAndPassword 确实返回了一个 Promise 服务中的方法(我猜是与问题无关,但是)看起来如下:public registerWithEmailAndPassword(register: RegisterDataModel): Promise&lt;void | string[]&gt; { const successMessages: string[] = []; const errorMessages: string[] = []; return new Promise&lt;void | string[]&gt;(((resolve, reject) =&gt; { this.createUserWithEmailCredentials(register, successMessages, resolve, errorMessages, reject); })); }跨度>
      • 好的,但是您没有调用原始方法。您正在调用默认情况下不返回任何内容的存根方法。使用 returnValue 也应该有效,但如前所述,promise 是异步的,因此您应该等待或强制打勾。
      • 你真的有一些代码要提供吗?我尝试了你提到的 fakeAsync it('should call navigate', fakeAsync(() =&gt; { const spy = (&lt;jasmine.Spy&gt;routerStub.navigate).and.stub(); (&lt;jasmine.Spy&gt;registryStub.registerWithEmailAndPassword).and.returnValue(Promise.resolve(() =&gt; ['test'])); component.onSubmit({username: 'test', email: 'test', password: 'test', passwordConfirm: 'test', termsAndCondition: true}); tick(); expect(spy).toHaveBeenCalledWith(['/completeSignUp']); })) 但我得到一个:msg.forEach 不是函数错误...这个单元测试很痛苦..
      • :) 抱歉,如果没有完整的代码,我们无法提供任何经过测试的东西。 fakeAsync 代码看起来不错。我假设您收到错误是因为调用了 Promise catch 回调并且参数不是数组。我注意到的几件事。 Promise.resolve 应该传递值 - Promise.resolve(['test'])。没有看到任何代码来模拟 router.navigate 方法的结果,这将由于 then 调用而导致错误。另外,验证 notificationService 没有抛出错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-02
      • 2016-09-30
      • 1970-01-01
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      相关资源
      最近更新 更多