mat*_*teo 23 javascript unit-testing jestjs es6-modules
我要测试的ES6模块如下所示:
function privateFunction() {
...
}
export function publicFunction() {
... does something ...
privateFunction()
... does something else ...
}
Run Code Online (Sandbox Code Playgroud)
我正在使用JEST进行单元测试,我正试图找到一种方法来测试publicFunction并通过模拟它来避免执行privateFunction,但我无法在模拟尝试中成功.任何的想法?
mat*_*teo 19
我发现了一种使用babel-plugin-rewire模块来模拟私有函数的方法.
在package.json中我有以下内容:
"devDependencies": {
...
"babel-plugin-rewire": "1.0.0-beta-5",
"babel-jest": "18.0.0",
...
Run Code Online (Sandbox Code Playgroud)
在.babel.rc我有以下内容:
{
"presets": [
"es2015",
"stage-0",
"react"
],
"env": {
"test": {
"plugins": [
"babel-plugin-rewire"
]
}
},
...
Run Code Online (Sandbox Code Playgroud)
此时我能够模拟私有函数:
import * as moduleToTest from './moduleToTest.js'
describe('#publicFunction', () => {
it('mocks private function', () => {
moduleToTest.__Rewire__('privateFunction', () => { console.log('I am the mocked private function') })
...
})
})
Run Code Online (Sandbox Code Playgroud)
小智 10
如果要模拟私有函数,请尝试使用原型。例如,您需要模拟以下类的privateFunction:
export class Module {
public publicFunction() {
// do something
this.privateFunction();
// do something
}
private privateFunction() {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
所以你应该在jest.spyOn函数中使用Module.prototype。
import { Module } from "./my-module";
describe('MyModule', () => {
it('tests public function', () => {
// Arrange
const module = new Module()
const myPrivateFunc = jest.spyOn(Module.prototype as any, 'privateFunction');
myPrivateFunc.mockImplementation(() => {});
// Act
module.publicFunction();
// Assert
expect(myPrivateFunc).toHaveBeenCalled();
});
});
Run Code Online (Sandbox Code Playgroud)
没有办法解决JavaScript的本质问题.该函数绑定到模块的范围,因此无法知道此函数是否存在于外部,因此无法访问该函数,最终无法模拟它.
也许更重要的是,您不应该测试被测对象的内部,而只测试公共API.因为这是重要的一切.只要公共API保持稳定,没有人关心内部是如何完成的.
另一种选择是显式强制转换:
const spy = jest.spyOn((someInstance as unknown) as { privateMethod: SomeClass['privateMethod'] }, 'privateMethod');
Run Code Online (Sandbox Code Playgroud)
它有点长,但它的优点是保留私有方法的类型以供后续检查,例如spy.hasBeenCalledWith(...).