我的代码类似于
function myFunc(condition){
if(condition){
process.exit(ERROR_CODE)
}
}
如何在Jest中测试?使用exit
覆盖process
中的jest.fn()
,并在测试后将其还原,但由于流程退出
答案 0 :(得分:13)
此线程中的其他建议将导致我的错误,其中使用process.exit
进行的任何测试都将无限期运行。以下选项对TypeScript适用于我,但对JavaScript也应适用:
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
myFunc(condition);
expect(mockExit).toHaveBeenCalledWith(ERROR_CODE);
要注意的是,仅使用spyOn
意味着仍会调用原始的process.exit()
函数,从而结束了进程线程并挂起了测试。最后使用mockImplementation
会将函数主体替换为所提供的函数(在我的示例中为空)。
此技巧对于打印到例如stdout的测试也很有用。例如:
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”调用一样,无论是否使用模拟实现,您都需要稍后对其进行还原,以避免缠结的模拟产生怪异的副作用。因此,请记住在当前测试用例的末尾调用以下两个函数:
mockExit.mockRestore()
mockStdout.mockRestore()
答案 1 :(得分:2)
您可以使用jest.spyOn
,因为这也会调用原始方法:
const exit = jest.spyOn(process, 'exit');
//run your test
expect(exit).toHaveBeenCalledWith('ERROR_CODE');
答案 2 :(得分:2)
对于大多数全局javascript对象,我尝试用我的存根替换并在测试后恢复。以下工作正常,我可以模仿process
。
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;
});
});
这有助于避免运行真实process.exit
以避免单元测试崩溃。
答案 3 :(得分:1)
我遇到了类似的问题。使用下面的代码解决了它
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')
答案 4 :(得分:0)
在导入我的模块之前,我在模拟 process.exit 时遇到了问题。所以在模拟之前导入有效。
const { foo } = require("my-module");
const realProcessExit = process.exit;
process.exit = jest.fn(() => { throw "mockExit"; });
afterAll(() => { process.exit = realProcessExit; });
describe("foo", () => {
it("should exit the program", () => {
try {
foo();
} catch (error) {
expect(error).toBe("mockExit");
expect(process.exit).toBeCalledWith(1);
}
});
});
(重要的是永远不要在模拟的 process.exit 中返回(抛出),所以 foo 不会继续控制流,就好像什么都没发生一样)
答案 5 :(得分:0)
这在监视 process#exit
并且 没有得到关于需要 // @ts-ignore
'ing 的模拟实现的方法签名的类型错误方面对我有用:
const processExit = jest
.spyOn(process, 'exit')
.mockImplementation((code?: number) => undefined as never);