如何使用 Jest 模拟测试 Node.js CLI?

And*_*dyO 6 node.js jestjs

我一开始就被困住了,只是需要 CLI 并捕获其输出。我尝试了两种方法,但都不起作用。

这是我的 cli.js:

#!/usr/bin/env node

console.log('Testing...');
process.exit(0);
Run Code Online (Sandbox Code Playgroud)

这是我的 cli.test.js:

test('Attempt 1', () => {
    let stdout = require("test-console").stdout;
    let output = stdout.inspectSync(function() {
        require('./cli.js');
    });
    expect(output).toBe('Testing...');
});

test('Attempt 2', () => {
    console.log = jest.fn();
    require('./cli.js');
    expect(console.log.calls).toBe(['Testing...']);
});
Run Code Online (Sandbox Code Playgroud)

实际运行哪个测试并不重要,输出总是:

$ jest

 RUNS  bin/cli.test.js
Done in 3.10s.
Run Code Online (Sandbox Code Playgroud)

Est*_*ask 8

Node.js CLI 应用程序与其他应用程序没有什么不同,只是它们对环境的依赖。预计他们将广泛使用process成员,例如:

  • process.stdin
  • process.stdout
  • process.argv
  • process.exit

如果使用了这些东西中的任何一个,它们应该被相应地模拟和测试。

由于console.log直接调用输出,所以直接监视它是没有问题的,尽管test-console也可以使用helper 包。

在这种情况下process.exit(0),在导入的文件中调用,因此规范文件提前退出,下一个Done输出来自父进程。应该打掉。抛出错误是必要的,以便停止代码执行 - 模仿正常行为:

test('Attempt 2', () => {
    const spy = jest.spyOn(console, 'log');
    jest.spyOn(process, 'exit').mockImplementationOnce(() => {
      throw new Error('process.exit() was called.')
    });

    expect(() => {
      require('./cli.js');
    }).toThrow('process.exit() was called.');
    expect(spy.mock.calls).toEqual([['Testing...']]);
    expect(process.exit).toHaveBeenCalledWith(0);
});
Run Code Online (Sandbox Code Playgroud)