【问题标题】:How do I properly mock Amplify for Unit Testing in Jasmine?如何在 Jasmine 中正确模拟 Amplify 以进行单元测试?
【发布时间】:2020-06-12 16:41:39
【问题描述】:

我是单元测试的新手,所以请耐心等待

我正在尝试对用于在 Angular 应用程序中使用 Amplify 记录用户的服务进行单元测试。

现在在我正在做的规范文件中:

 beforeEach(async () => {
        TestBed.configureTestingModule({
            imports: [
                HttpClientTestingModule,
            ],
            providers: [
                MyService, Amplify
            ]
        }
      myService = TestBed.get(MyService)
      amplify = TestBed.get(Amplify)
    })

   it('should login', async () => {
      const objToBeReturned = { signInUserSession: { idToken: { jwtToken: 'tokenValue' } } }
      spyOn(Amplify.Auth, 'signIn').and.returnValue(objToBeReturned)

      await myService.login('username', 'password')
   })

MyService 中:

  public async login(username: string, password: string) {
    const authUser = await Amplify.Auth.signIn(username.toLowerCase(), password)
    if (authUser.signInUserSession != null) {
      const idToken = authUser.signInUserSession.idToken.jwtToken
      return this.patientLogin(idToken)
    }
   }

  private async patientLogin(idToken?: string): Promise<boolean> {
    await this.sendRequest<LoginResponse>(url, data).pipe(
      tap(response => {
        if (!isLoginResponse(response)) {
          throw throwErr({ code: 'Generic' })
        }
        this.token = response.token
      })
    ).toPromise()
    return true
  }

这给了我错误异步函数没有在 5000 毫秒内完成

我很确定这取决于我嘲笑 Amplify 的方式

我如何正确地模拟它?

【问题讨论】:

  • 你的服务好像没有使用注入的Amplify,是直接调用的。
  • 关于如何正确执行的任何建议?问题是,如果我不模拟 signin 方法,我会收到错误:Cannot read property 'clientMetadata' of undefined

标签: angular unit-testing jasmine karma-jasmine


【解决方案1】:

试试:

   it('should login', async (done) => {
      spyOn(myService, 'patientLogin'); // assuming it is a public function
      const objToBeReturned = { signInUserSession: { idToken: { jwtToken: 'tokenValue' } } }
      // Promise.resolve is optional but since it is returning a promise and we are awaiting it, I think we should do it here as well.
      spyOn(Amplify.Auth, 'signIn').and.returnValue(Promise.resolve(objToBeReturned));
      console.log('calling login');
      await myService.login('username', 'password');
      // fixture.whenStable() can be optional as well, but I think it will be good to wait for all promises to finish
      console.log('login resolved');
      await fixture.whenStable();
      expect(myService.patientLogin).toHaveBeenCalledWith('tokenValue');
      // call the done function to tell the test you are done, I think this is what you were missing
      done();
   })

======编辑================

您必须找出测试卡在哪里,我认为this.patientLogin(idToken) 是异步的并且卡在那里。查看console.logs,确保您看到login resolved。基于这种预感,我发现了patientLogin,并断言它被调用了。

【讨论】:

  • 谢谢,但不幸的是它不起作用。不断收到同样的错误
  • 你是对的。从某种意义上说,测试卡在 patientLogin (我刚刚添加到我上面的问题中)所以如果我添加 spyOn&lt;any&gt;(communication, 'patientLogin') 它确实有效。不过我有点怀疑,监视您正在测试的服务不会违背测试的目的吗?
  • 好吧,既然您只是在测试登录,那么这是it('should login') 是一个很好的测试。然后您可以创建另一个it('patient login should work') 的测试并测试patientLogin。这就是它被称为单元测试的原因,您可以测试代码的位/单元,并确信如果每个位都在发挥作用,那么它们应该作为一个整体完成它们的工作。
【解决方案2】:

您可以使用jasmine方法callThrough,然后您可以检查Auth类的方法是否已被您的服务调用:

it('should login', async () => {
   spyOn(Auth, 'signIn').and.callThrough();

   await myService.login('username', 'password');
   expect(Auth['signIn']).toHaveBeenCalled();
});

【讨论】:

    猜你喜欢
    • 2022-10-08
    • 2013-10-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 2015-09-18
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    相关资源
    最近更新 更多