【问题标题】:How to mock a callback function to test a promise in with jasmine in Angular 8如何在 Angular 8 中模拟一个回调函数以使用 jasmine 测试一个 Promise
【发布时间】:2020-01-10 17:28:53
【问题描述】:

我有一个函数返回一个承诺并调用另一个函数,该函数将回调作为参数,但我无法弄清楚如何模拟回调函数或调用它的函数。

我要模拟的函数是来自我正在注入的服务的“listenOnAMessageWithCallBack”,我还想模拟它调用的回调函数。

我的实现:

  async getUsername(): Promise<string> {
    return await new Promise<string>((resolve, reject) => {
      try {
        this.electronController.sendMessage('userName');
        let cb = (event, username) =>{
          this.username = username;
          let user = this.stripDomain(this.username);
          resolve(user);
        };
        this.electronController.listenOnAMessageWithCallBack('catchUser', cb); 
      } catch (err) {
        reject(err);
      }
    })
  }

我的测试如下:

  it('testing function with callback', async() => {
    const stripDomain = spyOn(service, 'stripDomain').and.callFake(()=>{
      service.username = service.username.split('\\').reverse()[0];
      return service.username;
    });
    let cb = (event, username)=>{Promise.resolve('username')}
    spyOn(electronController, 'listenOnAMessageWithCallBack').withArgs('message').and.callFake(()=>{});
    let username = await service.getUsername();
    expect(username).toBe('username');
    expect(stripDomain).toHaveBeenCalledTimes(1);
  });

我在运行测试时收到以下错误: Spy 'listenOnAMessageWithCallBack' 收到了一个带有参数 ['catchUser', Function ] 的调用,但所有配置的策略都指定了其他参数。

如何模拟回调函数及其调用函数?

提前致谢。

【问题讨论】:

  • 我只是想通过一些自定义实现来存根一个方法,并偶然发现了这篇文章,并且问题中使用的 callFake 想法有所帮助。

标签: javascript typescript unit-testing jasmine angular8


【解决方案1】:

您收到该错误消息是因为您使用.withArgs('message') 配置了您的listenOnAMessageWithCallBack spy,因此只有在使用参数'message' 调用该方法时,您的spy 才会用于代替该方法。但是,在您的服务代码中,使用'catchUser' 和回调函数调用该方法,而不是使用'message',因此永远不会调用您的间谍。如果您删除.withArgs('message') 条件,则无论传递给实际方法的参数如何,都会调用您的间谍。

一旦你开始工作并且你的间谍被调用,那么在间谍的callFake 函数中,你可以在你的服务代码中获取传递给方法的回调:

spyOn(electronController, 'listenOnAMessageWithCallBack').and.callFake(
  (msg, cb) => {
    expect(msg).toBe('catchUser');
    expect(typeof cb).toBe('function');

    // cb here is the cb being passed into listenOnAMessageWithCallBack in your service
    // code, so you need to invoke it here yourself or the promise won't get resolved
    cb('mockEvent', 'mockUsername');
  }
);

您不能真正模拟回调,因为它是您服务中的一个局部变量,但由于您可以获取它并在测试中手动调用它,您应该能够测试它的效果。

不过,您需要弄清楚您希望代码做什么,因为该回调将 service.username 设置为传递给它的用户名,但在您的测试中看起来您正试图监视service.stripDomain 并改为设置 service.username。因此,您似乎需要在此处准确确定要测试的内容。

Here's a stackblitz 显示 callFake 工作并允许您访问回调函数。

【讨论】:

  • 非常感谢这帮助我解决了我的问题。我正在尝试执行流程,并在此过程中想到了模拟回调的可能性。使用您的解决方案,我能够测试回调的效果和承诺的解决方案。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-22
  • 2017-05-13
  • 2023-02-26
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 2016-09-03
相关资源
最近更新 更多