查了两天资料、issue最后总结有如题的三种方式可以部分替换模块中的某个函数,但死活就是没有效果,不知道问题到底是出在哪里了?有人用jest做过这种替换吗,请教
代码如下
// src/module.js
export const A = () => "function A";
export const B = () => A();
// test/mock.test.js
import * as Module from "../src/module";
it("jest.fn", () => {
Module.A = jest.fn().mockReturnValue("mock function");
const result = Module.toHaveBeenCalled();
expect(Module.A).toHaveBeenCalled();
expect(result).toEqual("mock function");
});
it("spyOn", () => {
const spy = jest.spyOn(Module, "A").mockImplementation(() => "mock function");
const result = Module.B();
expect(spy).toHaveBeenCalled();
expect(result).toEqual("mock function");
});
it("mock", () => {
jest.mock("../src/module", () => {
const original = jest.requireActual("../src/module");
return {
__esModule: true,
...original,
A: jest.fn(() => "mock function")
};
});
const module = require("../src/module");
const result = module.B();
expect(module.A).toHaveBeenCalled();
expect(result).toEqual("mock function");
});
模拟不起作用,是因为闭包的作用,B 中调用的并不是被模拟后的 A,而是实际的 A.
如果需要实现这种情况的模拟
一种方法是,修改源码如下
然后去模拟 A,这样当 B 去执行时就会找到 exports 下的 A.
第二种方法是,拆分
module.js
,将 A 拆分到另外一个文件a.js
文件,然后将 A 导入到module.js
中使用,这样直接去模拟a.js
也可以.第三种方法是,使用
Babel
插件,在编译的时候,添加一些额外的代码,实际上就是把需要手动去修改源码的过程,交给插件去自动完成了.这样的插件有:
这样可以在不用动源代码的情况下,完成需要的模拟功能.在我的
CodeSandbox
例子中,用的是babel-plugin-explicit-exports-references
CodeSandbox
更多详情 How to mock specific module function?