7

我想知道如何为 npm 包Inquirer.js编写单元测试,这是一个使 CLI 包更容易的工具。我已经阅读了这篇文章,但我无法让它发挥作用。

这是我需要测试的代码:

const questions = [
                {
                    type: 'input',
                    name: 'email',
                    message: "What's your email ?",
                },
                {
                    type: 'password',
                    name: 'password',
                    message: 'Enter your password (it will not be saved neither communicate for other purpose than archiving)'
                }
            ];

            inquirer.prompt(questions).then(answers => {
                const user = create_user(answers.email, answers.password);
                let guessing = guess_unix_login(user);
                guessing.then(function (user) {
                    resolve(user);
                }).catch(function (message) {
                    reject(message);
                });
            } );

...这是用 Mocha 编写的测试:

describe('#create_from_stdin', function () {
            this.timeout(10000);
            check_env(['TEST_EXPECTED_UNIX_LOGIN']);
            it('should find the unix_login user and create a complete profile from stdin, as a good cli program', function (done) {
                const user_expected = {
                    "login": process.env.TEST_LOGIN,
                    "pass_or_auth": process.env.TEST_PASS_OR_AUTH,
                    "unix_login": process.env.TEST_EXPECTED_UNIX_LOGIN
                };
                let factory = new profiler();
                let producing = factory.create();
                producing.then(function (result) {
                    if (JSON.stringify(result) === JSON.stringify(user_expected))
                        done();
                    else
                        done("You have successfully create a user from stdin, but not the one expected by TEST_EXPECTED_UNIX_LOGIN");
                }).catch(function (error) {
                    done(error);
                });
            });
        });

我想用process.env.TEST_LOGIN(回答第一个 Inquirer.js 问题)和process.env.TEST_PASS_OR_AUTH(回答第二个 Inquirer.js 问题)填充标准输入,以查看该函数是否创建了有效的配置文件(值 unix_logincreate由工厂对象)。

我试图了解 Inquirer.js 如何对自身进行单元测试,但我对 NodeJS 的理解还不够好。你能帮我做这个单元测试吗?

4

2 回答 2

10

您只需模拟或存根您不想测试的任何功能。

  • module.js- 您要测试的模块的简化示例

    const inquirer = require('inquirer')
    
    module.exports = (questions) => {
      return inquirer.prompt(questions).then(...)
    }
    
  • module.test.js

    const inquirer = require('inquirer')
    const module = require('./module.js')
    
    describe('test user input' () => {
    
      // stub inquirer
      let backup;
      before(() => {
        backup = inquirer.prompt;
        inquirer.prompt = (questions) => Promise.resolve({email: 'test'})
      })
    
      it('should equal test', () => {
        module(...).then(answers => answers.email.should.equal('test'))
      })
    
      // restore
      after(() => {
        inquirer.prompt = backup
      })
    
    })
    

有一些库可以帮助模拟/存根,例如sinon

inquirer.prompt在这种情况下也更容易模拟,因为.prompt它只是主导出上的一个属性,它将在和inquirer中引用同一个对象。对于更复杂的场景,有一些库可以提供帮助,例如proxyquire。或者,您可以创建模块以帮助您轻松切换依赖项以进行测试。例如:module.jsmodule.test.js

  • module.js- 使其成为“工厂”函数,它返回您的主函数,并自动(通过默认参数)或手动注入依赖项。

    module.exports = ({
      inquirer = require('inquirer'),
    } = {}) => (questions) => {
      return inquirer.prompt(questions).then(...)
    }
    
  • module.test.js

    const module = require('./module.js')
    
    describe('test user input' () => {
    
      const inquirer = {prompt: () => Promise.resolve({email: 'test'})};
    
      it('should equal test', () => {
        module({inquirer})(...).then(answers => answers.email.should.equal('test'))
      })
    })
    
于 2018-04-16T18:00:12.880 回答
1

inquirer.jsjest测试框架一起使用

  1. 嘲笑inquirer
  2. 模拟.prompt响应

模块-test.js

import module from './module';
import inquirer from 'inquirer';

jest.mock('inquirer');

describe('Module test', () => {
  test('user input', async () => {
    expect.assertions(1);
    inquirer.prompt = jest.fn().mockResolvedValue({ email: 'some@example.com' });

    await expect(module()).resolves.toEqual({ email: 'some@example.com' });
  });
});

(使用 ES6 或 TypeScript 语法。)

于 2018-08-22T14:12:39.227 回答