在玩笑模拟期间获取原始实现

PF1*_*PF1 4 javascript fetch node.js jestjs

我试图在 ESM 模块中临时模拟节点获取,同时仍然重新训练原始实现,以便我可以访问真实端点的值。但是,此错误显示“必须使用导入来加载 ES 模块”。我认识到对 ESM 的 jest 支持仍悬而未决 - 有没有办法在当前 Node、ES6 和 Jest 的组合中实现此行为?

Worker.ts(依赖项):

export default async () => {
    const response = await fetch("http://example2.org");
    return await response.json()
  }
Run Code Online (Sandbox Code Playgroud)

主要.测试.ts:

import { jest } from "@jest/globals";


jest.mock("node-fetch", () => {
    return Promise.resolve({
        json: () => Promise.resolve({ myItem: "abc" }),
    })
})

import doWork from './worker.js';
import mockedFetch from 'node-fetch';

const originalFetch = jest.requireActual('node-fetch') as any;

test("Ensure mock", async () => {
    const result = await doWork();
    expect(result.myItem).toStrictEqual("abc");
    expect(mockedFetch).toBeCalledTimes(1);

    const response = await originalFetch("http://www.example.org");
    expect(response.status).toBe(200);

    const result2 = await doWork();
    expect(result2.myItem).toStrictEqual("abc");
    expect(mockedFetch).toBeCalledTimes(2);
});
Run Code Online (Sandbox Code Playgroud)

mak*_*imr 5

首先,Jest不支持jest.mockESM模块进行测试

请注意,我们目前在 ESM 中不以干净的方式支持 jest.mock,但我们打算在将来添加适当的支持。请关注此问题以获取更新。

这是合理的,因为import与 具有不同的语义require。所有导入都会被提升,并将在模块加载时在任何模块代码之前进行评估。

因此,在您的情况下,因为您正在使用jest.mock 我假设您的测试代码已转换。在这种情况下,如果你想使用非“CommonJS”包,你也应该对其进行改造。您可以将transformIgnorePatternsjest 配置更改为[]. 这意味着来自的所有包都node_modules将经过转换。如果它太激进,您可以选择像这样忽略的特定模块"transformIgnorePatterns": [ "node_modules/(?!(node-fetch))" ],但不要忘记传递依赖项。;)

  • 添加/更改 jest 配置
  "transformIgnorePatterns": []
Run Code Online (Sandbox Code Playgroud)
  • jest.mock 接受模块工厂,它应该返回导出的代码。对于你的情况,你应该这样写。
jest.mock("node-fetch", () => {
  return {
    __esModule: true,
    default: jest.fn(() =>
      Promise.resolve({
        json: () => Promise.resolve({ myItem: "abc" }),
      })
    ),
  };
});
Run Code Online (Sandbox Code Playgroud)

如果你有错误

jest.mock() 的模块工厂不允许引用任何超出范围的变量

只需从导入中删除 jest 并将其用作全局变量或将其导入到模块工厂函数中 https://github.com/facebook/jest/issues/2567

  • 改成const originalFetch = jest.requireActual('node-fetch')
const originalFetch = jest.requireActual('node-fetch').default;
Run Code Online (Sandbox Code Playgroud)