NodeJS 为什么当被测文件的spied函数的导入被破坏时,Jest spy会中断?

b09cbbtk  于 9个月前  发布在  Node.js
关注(0)|答案(1)|浏览(94)

测试文件:

const webhook = require('../../../../../../src/lib/apis/webhook');

const internalFunc = jest.spyOn(webhook, 'handleWebhookCreation').mockImplementation(() => {
   return expectedReturn;
});

字符串
正在测试的文件:

const { handleWebhookCreation } = require('../../../apis/webhook');

const createWebhook = async (req, res) => {
    for (const webhook of payload) {
      results.push(await handleWebhookCreation(webhook, t));
    }
};


这不起作用。正常的函数被调用,而不是一个模拟/间谍版本
然后我发现,这修复了它,而不是解构方法,得到整个对象,然后调用它,如以下变化

const _webhook = require('../../../apis/webhook');
...
results.push(await _webhook.handleWebhookCreation(webhook, t));


现在,在我的单元测试中正确完成了spy/mocking
我不知道这是为什么,有人知道为什么吗?

z8dt9xmd

z8dt9xmd1#

这是一个时间的问题。将其缩减为测试通过的最小示例:

// webhook.js
module.exports = {
  handleWebhookCreation() {},
};
// consumer.js
const webhook = require("./webhook");

module.exports = {
  sut() {
    webhook.handleWebhookCreation();
  },
};
// consumer.test.js
const consumer = require("./consumer");
const webhook = require("./webhook");

jest.spyOn(webhook, "handleWebhookCreation");

it("works", () => {
  consumer.sut();
  expect(webhook.handleWebhookCreation).toHaveBeenCalled();
});

在这种情况下:

  1. consumerconsumer.test都是require相同的对象,并将其命名为webhook;
    1.测试监视webhook对象的handleWebhookCreation属性;
    1.测试调用消费者,消费者访问webhook的(spied!)handleWebhookCreation属性并调用它。
    如果我们重写以在消费者中解构:
// consumer.js
const { handleWebhookCreation } = require("./webhook");

module.exports = {
  sut() {
    handleWebhookCreation();
  },
};


现在:

  1. consumerconsumer.test都需要相同的对象-后者将其命名为webhook,但前者访问(unspied!)handleWebhookCreation属性并将其命名为handleWebhookCreation;
    1.测试监视webhook对象的handleWebhookCreation属性;
    1.测试调用消费者,消费者调用它在应用间谍之前访问的handleWebhookCreation
    重写以完全避免此问题的一种方法是jest.mock整个模块(在任何其他导入之前被提升),而不是监视它的一部分:
// consumer.test.js
const consumer = require("./consumer");
const webhook = require("./webhook");

jest.mock("./webhook");

it("works", () => {
  consumer.sut();
  expect(webhook.handleWebhookCreation).toHaveBeenCalled();
});


这是一种更健壮的方法--您 * 应该 * 能够在通过测试的情况下重构代码,从而给予信心,使您相信这是一种行为保留更改,而不是不断地重写测试。

相关问题