Javascript 在函数中模拟函数并获得调用计数
在Javascript 在函数中模拟函数并获得调用计数,javascript,unit-testing,mocking,jestjs,Javascript,Unit Testing,Mocking,Jestjs,在script.js中考虑此模块: const randomizeRange = (min, max) => { return Math.floor(Math.random() * (max - min) + min); }; const randomArr = (n, min, max) => { const arr = []; for (let i = 0; i < n; i++) { arr.push(randomizeRange(min, max)
script.js
中考虑此模块:
const randomizeRange = (min, max) => {
return Math.floor(Math.random() * (max - min) + min);
};
const randomArr = (n, min, max) => {
const arr = [];
for (let i = 0; i < n; i++) {
arr.push(randomizeRange(min, max));
}
return arr;
};
module.exports = { randomArr, randomizeRange };
我很感激你试图理解这个问题,所以我会尽我所能回答你。我通常建议您不要模拟函数,除非您正在对服务器或数据库或其他对象进行某种复杂的后端调用。您可以使用真实代码(而不是模拟代码)进行更真实的测试,这将带来无穷的好处。这将是我给你今后的建议 但是为了这个问题的目的-这里是发生了什么 您没有看到模拟以正确的方式工作的原因是,您实际上创建了两个独立的模拟:
- 您已经为
创建了一个模拟randomizarr
- 您已经为
创建了另一个单独的模拟randomizerage
randomArrMock(100,20,1000)
时,这将调用您指定的randomizerar
的单个mock,但该mock绝对没有randomizerage
的其他mock的概念。所以它从不在幕后调用。因此,这就是为什么您在末尾看到调用量为0
这里只需稍微更改一下设置,指定调用了哪些mock,以及何时调用,以便看到这两者按照您的预期协同工作
实际上,我在这里选择的是而不是来模拟你的随机化方法。该方法调用了Math.floor
,在本例中,这将更容易“监视”(这是对我们将要使用的方法的提示)。该Math.floor
方法在每次调用randomizerage
时都会被调用一次,因此它将是一个理想的选择。它也应该被调用100次
,与您的方法相同
我们之所以选择spyOn
方法,而不是像您已经做过的那样使用实际的模拟,是因为我们希望保持原始行为,因此在不覆盖预期行为的情况下监视方法被调用的次数是理想的
因此,请将现有的模拟对象保留为randomizarr
,如下所示:
const randomArrMock = jest.fn(randomArr);
现在为Math.floor
const mathFloorSpy = jest.spyOn(Math.prototype, `floor`);
此“间谍”将有效地监视此方法,而不会覆盖其行为。如果愿意,您可以覆盖该行为,但我们希望在计算调用次数的同时保持该行为的完整性
现在,当您运行测试套件时:
test("tests for randomArr", () => {
expect(randomArrMock(100, 20, 1000)).toHaveLength(100);
expect(randomArrMock.mock.calls.length).toBe(1)
expect(mathFloorSpy.mock.calls.length).toBe(100)
});
现在这将作为Math传递。每次调用randomizerage
方法时,都会调用floor
最后,当您的测试完成时,不要忘记使用以下方法恢复原始的Math.floor
功能:
mathFloorSpy.mockRestore();
快乐测试 我很感激你试图理解这个问题,所以我会尽我所能回答你。我通常建议您不要模拟函数,除非您正在对服务器或数据库或其他对象进行某种复杂的后端调用。您可以使用真实代码(而不是模拟代码)进行更真实的测试,这将带来无穷的好处。这将是我给你今后的建议
但是为了这个问题的目的-这里是发生了什么
您没有看到模拟以正确的方式工作的原因是,您实际上创建了两个独立的模拟:
- 您已经为
randomizarr
创建了一个模拟
- 您已经为
randomizerage
创建了另一个单独的模拟
当您在测试中调用randomArrMock(100,20,1000)
时,这将调用您指定的randomizerar
的单个mock,但该mock绝对没有randomizerage
的其他mock的概念。所以它从不在幕后调用。因此,这就是为什么您在末尾看到调用量为0
这里只需稍微更改一下设置,指定调用了哪些mock,以及何时调用,以便看到这两者按照您的预期协同工作
实际上,我在这里选择的是而不是来模拟你的随机化方法。该方法调用了Math.floor
,在本例中,这将更容易“监视”(这是对我们将要使用的方法的提示)。该Math.floor
方法在每次调用randomizerage
时都会被调用一次,因此它将是一个理想的选择。它也应该被调用100次
,与您的方法相同
我们之所以选择spyOn
方法,而不是像您已经做过的那样使用实际的模拟,是因为我们希望保持原始行为,因此在不覆盖预期行为的情况下监视方法被调用的次数是理想的
因此,请将现有的模拟对象保留为randomizarr
,如下所示:
const randomArrMock = jest.fn(randomArr);
现在为Math.floor
const mathFloorSpy = jest.spyOn(Math.prototype, `floor`);
此“间谍”将有效地监视此方法,而不会覆盖其行为。如果愿意,您可以覆盖该行为,但我们希望在计算调用次数的同时保持该行为的完整性
现在,当您运行测试套件时:
test("tests for randomArr", () => {
expect(randomArrMock(100, 20, 1000)).toHaveLength(100);
expect(randomArrMock.mock.calls.length).toBe(1)
expect(mathFloorSpy.mock.calls.length).toBe(100)
});
现在这将作为Math传递。每次调用randomizerage
方法时,都会调用floor
最后,当您的测试完成时,不要忘记使用以下方法恢复原始的Math.floor
功能:
mathFloorSpy.mockRestore();
快乐测试 这似乎是一个常见的问题,我能找到的最“正式”的解决方案是在Jest GitHub问题页面上的
因为您使用的是require
而不是