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不会抱怨;