问题
I was wondering how to write unit tests for the npm package Inquirer.js, which is a tool to make CLI package more easily. I have read this post but I was't able to make it works.
Here is my code that needs to be tested:
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);
});
} );
...and here is the test, written with 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);
});
});
});
I'd like to fill stdin with the process.env.TEST_LOGIN
(to answer the first Inquirer.js question) and process.env.TEST_PASS_OR_AUTH
(to answer the second Inquirer.js question) to see if the function create a valid profile (with the value unix_login guessed by the method create
of the factory object).
I tried to understand how Inquirer.js unit tests itself, but my understanding of NodeJS isn't good enough. Can you help me with this unit test?
回答1:
You simply mock or stub any functionality that you don't want to test.
module.js
- simplified example of a module you want to testconst 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 }) })
There are libraries to help with mocking/stubbing, like sinon.
Also it was easier to mock inquirer.prompt
in this case because .prompt
was just a property on the main export inquirer
which will refer to the the same object in both module.js
and module.test.js
. For more complicated scenarios there are libraries that can help, like proxyquire. Or you can create your modules in a way that help you switch out the dependencies easily for testing. For example:
module.js
- make it a "factory" function which returns your main function with dependencies injected either automatically (via default arguments) or manually.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')) }) })
回答2:
Using inquirer.js
with jest
testing framework
- Mock
inquirer
- Mock
.prompt
with response
module-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' });
});
});
(Using ES6 or TypeScript syntax.)
来源:https://stackoverflow.com/questions/49862039/how-to-write-unit-tests-for-inquirer-js