Javascript stubing process.exit with jest
我有这样的代码Javascript stubing process.exit with jest,javascript,mocking,jestjs,spy,Javascript,Mocking,Jestjs,Spy,我有这样的代码 function myFunc(condition){ if(condition){ process.exit(ERROR_CODE) } } 我怎么能开玩笑地测试这个呢?使用jest.fn()覆盖process中的exit,并在测试失败后将其返回,因为进程退出 const exit = jest.spyOn(process, 'exit'); //run your test expect(exit).toHaveBeenCalledWith('ERROR_
function myFunc(condition){
if(condition){
process.exit(ERROR_CODE)
}
}
我怎么能开玩笑地测试这个呢?使用
jest.fn()
覆盖process
中的exit
,并在测试失败后将其返回,因为进程退出
const exit = jest.spyOn(process, 'exit');
//run your test
expect(exit).toHaveBeenCalledWith('ERROR_CODE');
对于大多数全局javascript对象,我尝试在测试后用存根替换并恢复。下面的代码对我模拟过程非常有用
describe('myFunc', () => {
it('should exit process on condition match', () => {
const realProcess = process;
const exitMock = jest.fn();
// We assign all properties of the "real process" to
// our "mock" process, otherwise, if "myFunc" relied
// on any of such properties (i.e `process.env.NODE_ENV`)
// it would crash with an error like:
// `TypeError: Cannot read property 'NODE_ENV' of undefined`.
global.process = { ...realProcess, exit: exitMock };
myFunc(true);
expect(exitMock).toHaveBeenCalledWith(ERROR_CODE);
global.process = realProcess;
});
});
这有助于避免运行真正的过程。退出以避免单元测试崩溃。我遇到了类似的问题。用下面的代码解决了这个问题
const setProperty = (object, property, value) => {
const originalProperty = Object.getOwnPropertyDescriptor(object, property)
Object.defineProperty(object, property, { value })
return originalProperty
}
const mockExit = jest.fn()
setProperty(process, 'exit', mockExit)
expect(mockExit).toHaveBeenCalledWith('ERROR_CODE')
此线程中的其他建议将导致我端出现错误,任何带有process.exit
的测试都将无限期运行。以下选项适用于我的TypeScript,但也适用于JavaScript:
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
myFunc(condition);
expect(mockExit).toHaveBeenCalledWith(ERROR_CODE);
问题是,简单地使用spyOn
意味着仍然调用原始的process.exit()
函数,从而结束进程线程和挂起测试。最后使用mockImplementation
将函数体替换为提供的函数(在我的示例中为空)
这个技巧对于打印到(比如)标准输出的测试也很有用。例如:
const println = (text: string) => { process.stdout.write(text + '\n'); };
const mockStdout = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});
println('This is a text.');
expect(mockStdout).toHaveBeenCalledWith('This is a text.\n');
这将使您能够测试打印的值,并具有不使CLI控制台输出与随机换行符混淆的额外好处
请注意:与任何“jest.spyOn”调用一样,无论是否使用mock实现,您都需要稍后恢复它,以避免延迟mock的奇怪副作用。因此,记住在当前测试用例结束时调用以下两个函数:
mockExit.mockRestore()
mockStdout.mockRestore()
导入模块之前,我在模拟process.exit时遇到问题。因此,在模拟之前导入是有效的
const{foo}=require(“我的模块”);
const realProcessExit=process.exit;
process.exit=jest.fn(()=>{抛出“mockExit”;});
毕竟(()=>{process.exit=realProcessExit;});
描述(“foo”,()=>{
它(“应该退出程序”,()=>{
试一试{
foo();
}捕获(错误){
expect(error).toBe(“mockExit”);
expect(process.exit).toBeCalledWith(1);
}
});
});
(重要的是不要在模拟流程中返回(抛出)。退出,这样foo就不会继续控制流,就好像什么都没有发生一样)这对我来说很有效,因为我监视流程#退出
,并且不会得到有关模拟实现的方法签名的类型错误,这需要/@ts ignore
:
const processExit = jest
.spyOn(process, 'exit')
.mockImplementation((code?: number) => undefined as never);
这对我来说不起作用--jest运行,然后在调用退出代码时退出自己..我能够让它使用const exit=jest.spyOn(进程,“退出”).mockImplementation(数字=>number)代码>这就像我的Typescript节点后端单元测试中的一个魅力!Typescript可能存在一些奇怪的问题(可能是我的),但我无法实现上述功能--一直抱怨重新分配global.process=和mock类型不是正确的exit:etc类型,然后在运行它时崩溃。。mockImplementationOnce将在typescript中抱怨,因为进程出口预期永远不会返回,这里我们返回{}一种可能是在模拟实现中抛出一个错误,该错误的返回类型也将永远不会:const mockExit=jest.spyOn(进程,'exit').mockImplementation(()=>{throw new error('mock');})代码>另一种可能是强制间谍的返回类型为“void”,这样Typescript就不会抱怨了。回答得好!PS:不需要为mockImplementation
传递箭头函数,除非您必须在测试范围上设置变量等等。如果您执行const mockExit=jest.spyOn(进程,'exit')。mockImplementation(()=>{return undefined as never}),Typescript不会抱怨;