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

时间:2018-05-16 21:09:05

标签: node.js jestjs

我一开始就陷入困境,只需要CLI并捕获其输出。我尝试过两种方法,但两种方法都不起作用。

这是我的cli.js:

#!/usr/bin/env node

console.log('Testing...');
process.exit(0);

这是我的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...']);
});

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

$ jest

 RUNS  bin/cli.test.js
Done in 3.10s.

1 个答案:

答案 0 :(得分:2)

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

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

如果使用任何这些东西,应该对它们进行嘲笑和测试。

由于console.log是直接调用输出的,所以直接监视它是没有问题的,虽然也可以使用test-console之类的辅助包。

在这种情况下,process.exit(0)在导入的文件中被调用,因此spec文件提前退出,下一个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);
});