【问题标题】:Jest mockImplementation(Promise.resolve) returns undefined when spying on an object called from another class (Node.js)Jest mockImplementation(Promise.resolve)在监视从另一个类(Node.js)调用的对象时返回未定义
【发布时间】:2021-07-23 01:09:08
【问题描述】:

我无法让 Jest mockImplementation 在特定上下文中使用 Promise.resolve() 返回数据。

在我的 Node.js 代码中,我有一个结构,它将所有 API 调用代码放在一个类 (Api) 中,并将所有业务逻辑放在另一个类 (Repo) 中。当你实例化 Repo 时,它会为自己创建一个 Api 类的实例:this.api = new Api()

我正在尝试在 Repo 级别测试一个函数,并模拟 Api 调用,因此我们实际上在测试期间不会进行任何查询。

  const data = { postId: 3, id: 3, name: 'Bob Your Uncle' };
  beforeEach(() => {
    getSpy = jest.spyOn(repo.api, 'getPage').mockImplementation(() => {
      Promise.resolve(data);
    });
  });

当我执行该函数时,expect(getSpy).toHaveBeenCalledTimes(1) 返回 true,但它返回的值是“未定义”,而不是预期的承诺已解决。

当我对代码进行实际运行时,它工作得很好,但测试失败了。我怀疑这个问题可能与我正在测试的代码正在调用第二个用户编写的类这一事实有关,我不确定。我发现这个问题Jest: Spy on object method? 似乎相关,但他们的解决方案(将 .prototype 添加到 spyOn 参数中)并没有帮助我——他们使用的是原生 JS 对象而不是用户定义的对象,这似乎足够不同解释差异。

这是完整的describe 块:

describe('Repo: fetchRand', () => {
  const data = { postId: 3, id: 3, name: 'Bob Your Uncle' };
  beforeEach(() => {
    getSpy = jest.spyOn(repo.api, 'getPage').mockImplementation(() => {
      Promise.resolve(data);
    });
  });
  afterEach(() => {
    jest.clearAllMocks();
  });
  it('should fetch call this.api.getPage once', async () => {
    let res = await repo.fetchRand();
    expect(getSpy).toHaveBeenCalledTimes(1);
  });
  it('should return an object with a postId and an name', async () => {
    let res = await repo.fetchRand();
    expect(res).toHaveProperty('postId');
    expect(res).toHaveProperty('name');
  });
});

以及被测试的模块:

const Api = require('./Api');

module.exports = class Repository {
  constructor() {
    this.api = new Api();
  }
  async fetchRand() {
    let id = this.getRandomInt(5);
    let res = await this.api.getPage(id);
    return res;
  }
  getRandomInt(max) {
    return Math.floor(Math.random() * max) + 1;
  }
};

还有一个指向a GitHub repo with the full code 的链接——运行npm test -- Repo.test.js 来复制问题。 (这不是我真正的项目,只是复制问题基本性质的最简单的完整代码。)

【问题讨论】:

  • 再次检查语法,它没有返回承诺。有mockResolvedValue让意图更明确。
  • 感谢@EstusFlask——我不明白为什么它没有返回承诺,但mockResolvedValue 为我工作。我是 Jest 的新手,我每天都在寻找新的方法来搞砸;)

标签: javascript node.js unit-testing async-await jestjs


【解决方案1】:

问题是特定于 JavaScript 箭头语法而不是 Jest。 getPage spy 不返回承诺,所以它返回 undefined

应该使用不带括号的隐含返回:

.mockImplementation(() => (
  Promise.resolve(data);
));

或显式返回:

.mockImplementation(() => {
  return Promise.resolve(data);
});

返回 promise 的 spy 实现的捷径是:

.mockResolvedValue(data);

【讨论】:

    【解决方案2】:

    Estus Flask 的评论让我找到了写答案。与同类中的业务完全无关,我猜只是使用了错误的模拟。

    这个改变奏效了:

    getSpy = jest.spyOn(repo.api, 'getPage').mockResolvedValue(data);
    

    【讨论】:

      猜你喜欢
      • 2018-10-02
      • 2016-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-12
      • 1970-01-01
      • 2017-05-15
      • 1970-01-01
      相关资源
      最近更新 更多