请帮助我理解 Jest 模拟。
我已将一些虚拟函数放入文件中:
// actions.js
export function f1() {
return 1
}
export function calls_f1() {
f1()
}
然后在我的测试文件中,我试图了解如何检查一个函数调用另一个函数:
import * as actions from './actions.js'
describe("MOCKS", () => {
actions.f1 = jest.fn();
actions.calls_f1();
expect(actions.f1).toBeCalled();
});
但是测试失败,表示未调用模拟函数。我也尝试过交换测试的第二行和第三行,但没有成功。
我的 Jest 配置一切都很好,实际上我已经做了很多其他有效的测试(在同一个文件中)。
我在这里缺少什么?
注意:这个的实际实现(我在这里大大简化)涉及一个 actions
文件,其中包含一个调用私有(private)函数的公共(public)导出函数 fetchStations()
(或者更确切地说,不导出)导出函数_downloadStations()
。我正在尝试测试 _downloadStations()
是否被调用。
我使用 import * as actions
只是为了方便,所以我可以编写该行,然后使用 actions.whatever()
下文件导出的任何函数(而当我决定使用它们时,不必将函数添加到导入语句中)。如果 import * as actions
有一些我没有注意到的效果(正如下面的 brian 所暗示的),那么我当然不必使用它,并且可以使用 import {thisAction, thatAction} from './actions'
当然。
最佳答案
这一行:
import * as actions from './actions.js'
将模块导出从 actions.js
绑定(bind)到 actions
...
...因此将 actions.f1
设置为模拟函数会替换 f1
的模块导出...
...但这不会影响 calls_f1
,因为它直接调用 f1
。
如果将 calls_f1
更改为调用 f1
的模块导出,那么它将调用模拟函数。
有两种方法可以实现这一点。
一种方法是将 f1
移动到它自己的模块中。
另一种方法是注意 ES6 模块 "support cyclic dependencies automatically" (ES6 模块的一个主要设计目标)因此模块可以导入自己的导出:
actions.js
import * as actions from './actions'; // <= import the module...
export function f1() {
return 1
}
export function calls_f1() {
actions.f1() // <= ...and use it to call f1
}
actions.test.js
import * as actions from './actions.js'
describe('actions', () => {
it('calls_f1 should call f1', () => {
actions.f1 = jest.fn();
actions.calls_f1();
expect(actions.f1).toBeCalled(); // Success!
})
})
更新
OP 更新了问题以表明有问题的函数未从模块中导出。
在这种情况下,它只是模块的内部实现细节,无法直接监视。
测试它需要测试它所造成的影响,而不是直接监视它以查看它是否被调用。
关于unit-testing - 在 Jest 中没有调用 Mock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56045432/