(基于此处已经提供的示例。) 对于下面的模块,
// fruit.js
export const apple = 'apple';
export const strawberry = () => 'strawberry';
export default () => `banana and ${strawberry()} `;
我想编写一个测试来验证 default 导出函数是否正确调用函数 strawberry。 为了实现这一目标,我尝试了以下测试,
// partial_mock.js
import defaultExport, { strawberry } from '../fruit';
jest.mock('../fruit', () => {
const originalModule = require.requireActual('../fruit');
const mockedModule = jest.genMockFromModule('../fruit');
// Mock the exported 'strawberry' function.
return Object.assign({}, mockedModule, originalModule, {
strawberry: jest.fn(() => 'mocked strawberry'),
});
});
it('does a partial mock', () => {
expect(strawberry()).toBe('mocked strawberry');
const defaultExportResult = defaultExport();
expect(defaultExportResult).toBe('banana and mocked strawberry');
});
但是,不会调用模拟函数,而是调用实际函数。
× does a partial mock (21ms)
● does a partial mock
expect(received).toBe(expected) // Object.is equality
Expected: "banana and mocked strawberry"
Received: "banana and strawberry "
这是预期的吗?
我的测试有效吗?我在测试中错过了什么吗?
发生的事情是,当 Jest 导入
fruit.js
以从中生成模拟时,默认导出中的匿名函数已经在其闭包中获取了对其实际 strawberry
的引用。
所以 Jest 所做的只是嘲笑
strawberry
稍后导入它的任何其他模块,例如你的测试套件。
本文介绍了解决此问题的一些方法:https://medium.com/@qjli/how-to-mock-specific-module-function-in-jest-715e39a391f4
我的建议是在采用任何解决方法之前考虑重构你的逻辑:
fruit.js
中的某些函数是否用作实现细节或用于分解逻辑?也许您可以将它们视为私有类方法,并通过 defaultExport
本身来测试它们。如果它们的逻辑如此独立以至于需要在测试之间进行模拟,也许这些功能应该驻留在单独的模块中?