如何使用 javascript jest 监视导出的独立函数?

Kem*_*siz 2 javascript unit-testing mocking typescript jestjs

这是一个非常简单的场景,但我一直在努力寻找答案。

助手.ts:

export function foo() {
    bar();
}

export function bar() {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

helpers.spec.ts:

import { foo, bar } from "./helpers";

describe("tests", () => {
    it("example test", () => {
        const barSpy = // how can i set this up?
        foo();
        expect(barSpy).toHaveBeenCalled();
    });
});
Run Code Online (Sandbox Code Playgroud)

我不能这样做const spy = jest.spyOn(baz, 'bar');,因为我没有模块/类来代替“baz”。它只是一个导出函数。

编辑Jest 模拟内部函数已被建议作为重复项,但不幸的是它对我的场景没有帮助。

该问题的解决方案:

  • 移至单独的模块:我无法针对我的场景执行此操作。如果我测试应用程序中的每个功能,这将导致我创建 10 个新文件,这并不理想。(澄清一下,我认为这个解决方案可行,但我不能将它用于我的场景。我已经在这个测试文件中成功模拟了一个单独的文件函数。)

  • 将模块导入自身:

helpers.spec.ts:

import * as helpers from "./helpers";

describe("tests", () => {
    it("example test", () => {
        const barSpy = jest.spyOn(helpers, 'bar');
        foo();
        expect(barSpy).toHaveBeenCalled();
    });
});
Run Code Online (Sandbox Code Playgroud)

结果是:

expect(jest.fn()).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls:    0
Run Code Online (Sandbox Code Playgroud)

Ron*_*Ron 5

这是封闭的解决方案:

export function bar() {
  // do something
}

export function foo() {
  exports.bar();   // <-- have to change to exports.bar() instead of bar()
  // or this.bar(); would also work.
}

Run Code Online (Sandbox Code Playgroud)
import * as utils from './utils';

describe('tests', () => {
  it('example test', () => {
    const barSpy = jest.spyOn(utils, 'bar');
    utils.foo();
    expect(barSpy).toHaveBeenCalled();
  });
});

Run Code Online (Sandbox Code Playgroud)

或者看看这个重复的问题

  • `exports.bar()` 依赖于 ES 模块被转换为 CommonJS 的事实,这通常是一个错误。 (2认同)