这个问题涉及测试 javascript 和模拟函数。
假设我有一个如下所示的模块:
export function alpha(n) {
return `${n}${beta(n)}${n}`;
}
export function beta(n) {
return new Array(n).fill(0).map(() => ".").join("");
}
那么我无法通过以下方式测试它:
import * as indexModule from "./index";
//Not what we want to do, because we want to mock the functionality of beta
describe("alpha, large test", () => {
it("alpha(1) returns '1.1'", () => {
expect(indexModule.alpha(1)).toEqual("1.1"); //PASS
});
it("alpha(3) returns '3...3'", () => {
expect(indexModule.alpha(3)).toEqual("3...3"); //PASS
});
});
//Simple atomic test
describe("beta", () => {
it("beta(3) returns '...'", () => {
expect(indexModule.beta(3)).toEqual("..."); //FAIL: received: 'x'
});
});
//Here we are trying to mutate the beta function to mock its functionality
describe("alpha", () => {
indexModule.beta = (n) => "x";
it("works", () => {
expect(indexModule.alpha(3)).toEqual("3x3"); //FAIL, recieved: '3...3'
});
});
但是,如果将模块分成两个:
alpha.js
import { beta } from "./beta";
export function alpha(n) {
return `${n}${beta(n)}${n}`;
}
beta.js
export function beta(n) {
return new Array(n).fill(0).map(() => ".").join("");
}
然后我可以改变 beta 模块,并且 alpha 知道它:
import { alpha } from "./alpha";
import * as betaModule from "./beta";
describe("alpha", () => {
betaModule.beta = (n) => "x";
it("works", () => {
expect(alpha(3)).toEqual("3x3"); //PASS
});
});
为什么会这样呢?我正在寻找技术上具体的答案。
我有一个包含此代码的 Github 分支here,参见mutateModule
and singleFunctionPerModuleAndMutate
文件夹。
作为一个附加问题 - 在此示例中,我通过直接重新分配属性来改变模块。我是否正确理解使用笑话模拟功能本质上会做同样的事情?
IE。如果第一个示例不起作用而第二个示例不起作用的原因是由于突变,那么它必然意味着使用 jest 模块模拟函数同样不起作用。
据我所知 - 在测试该模块时没有办法模拟模块中的单个函数,正如这个笑话 github issues 所谈论的。我想知道的是为什么会这样。