我要测试的ES6模块如下所示:
function privateFunction() {
...
}
export function publicFunction() {
... does something ...
privateFunction()
... does something else ...
}
我正在使用JEST进行单元测试,我试图找到一种方法来测试publicFunction并通过模拟它来避免执行privateFunction,但我无法在模拟尝试中成功。有什么想法吗?
答案 0 :(得分:13)
我找到了一种使用 babel-plugin-rewire 模块来模拟我的私人功能的方法。
在 package.json 中,我有以下内容:
"devDependencies": {
...
"babel-plugin-rewire": "1.0.0-beta-5",
"babel-jest": "18.0.0",
...
在 .babel.rc 中,我有以下内容:
{
"presets": [
"es2015",
"stage-0",
"react"
],
"env": {
"test": {
"plugins": [
"babel-plugin-rewire"
]
}
},
...
此时我能够模拟私有函数:
import * as moduleToTest from './moduleToTest.js'
describe('#publicFunction', () => {
it('mocks private function', () => {
moduleToTest.__Rewire__('privateFunction', () => { console.log('I am the mocked private function') })
...
})
})
答案 1 :(得分:5)
没有办法解决JavaScript的本质问题。该函数绑定到模块的范围,因此无法知道此函数是否存在于外部,因此无法访问该函数,最终无法模拟它。
也许更重要的是,您不应该测试被测对象的内部,而只测试公共API。因为这是重要的一切。只要公共API保持稳定,就没有人关心内部的内容。
答案 2 :(得分:1)
如果要模拟私有功能,请尝试使用 prototype 。 例如,您需要模拟下一个类的 privateFunction :
xcode-select -p
因此,您应该在 jest.spyOn 函数中使用 Module.prototype 。
export class Module {
public publicFunction() {
// do something
this.privateFunction();
// do something
}
private privateFunction() {
// do something
}
}
答案 3 :(得分:0)
没有什么可以阻止您嘲笑私有函数。不要忘记,作为模拟插入的任何内容都将替换为模块;如果您无法访问要测试的功能,请自己添加该功能。
假设您有一些要测试的课程。
export class MyModule {
public myPublicFunc() {
return this.myPrivateFunc();
}
private myPrivateFunc() {
return 5;
}
}
您可以像这样测试。
import { MyModule } from './whatever'
describe('MyModule public function', () => {
it('should call a private function', () => {
// Arrange
const mod = new MyModule();
mod.myPrivateFunc = jest.fn();
// Act
mod.myPublicFunc();
// Assert
expect(mod.myPrivateFunc).toHaveBeenCalled();
});
});
如果您做的和我完全一样,Typescript会抱怨,但是您可以通过类型转换来解决。