我最近遇到了一个无法解释的问题。我在这些测试中有很多代码,所以我会尽力在这里捕获这个想法
我的测试看起来像:
describe('main page', function(){
beforeEach(function(done){
addUserToMongoDb(done); // #1
});
afterEach(function(done){
removeUserFromMongoDb(done);
});
context('login', function(){
it('should log the user in, function(){
logUserIn(user_email); // #2 - This line requires the user from the beforeEach
});
});
context('preferences', function(){
before(function(done){ //#3
logUserInBeforeTest(user_email);
});
it('should show the preferences', function(){
doCheckPreferences(); // #4
});
});
});
问题是,#1
的beforeEach运行良好。我可以在数据库和#2
传递的测试中看到它发生。
但是,#4
的首选项上下文中的测试失败,因为它无法找到用户在#3
登录它们。
似乎上下文before
在描述beforeEach
之前执行,导致它们失败。如果我将logUserIn
移到it
块中,则可以正常工作。
是什么导致这种情况?
答案 0 :(得分:23)
我发现了类似的问题。该文档具有误导性,因为"在此块之前"意味着(至少对我来说)"在此之前描述部分"。同时它意味着在任何描述部分"之前。检查此示例:
describe('outer describe', function () {
beforeEach(function () {
console.log('outer describe - beforeEach');
});
describe('inner describe 1', function () {
before(function () {
console.log('inner describe 1 - before');
});
describe('inner describe 2', function () {
beforeEach(function () {
console.log('inner describe 2 - beforeEach');
});
});
// output will be:
// inner describe 1 - before
// outer describe - beforeEach
// inner describe 2 - beforeEach
在您的层次结构中放置before
的位置似乎并不重要 - 它将在任何描述之前运行,而不是在其包含描述之前运行。
答案 1 :(得分:9)
混淆的原因在于摩卡的文档。 您可以在mocha中找到:
测试可以在你的钩子之前,之后或穿插中出现。钩子将按其定义的顺序运行,视情况而定;所有before()挂钩运行(一次),然后任何beforeEach()挂钩,测试,任何afterEach()挂钩,最后挂钩()挂钩(一次)。
讨论的挂钩before
和beforeEach
分别在所有或it
之前执行 - 在描述部分之前无法执行它。
在这里你可以find回答mocha主分支的#1贡献者添加类似beforeDescribe
hook的内容。
我认为您应该查看--delay
mocha option。
答案 2 :(得分:0)
关键是要制作mocha.opts
文件,其行指向./test/bootstrap.js
,在您之前,beforeAll,after,afterAll钩子处应用。
Execute all tests:
- npm test
Execute a single test:
- NODE_ENV=test node --inspect ./node_modules/.bin/_mocha --opts test/mocha.opts test/test/service/unSubscriber.test.js
node --inspect
标志进行调试
/package.json
{
"name": "app",
"version": "0.0.1",
"engines": {
"node": "11.9.0",
"npm": "6.5.0"
},
"scripts": {
"test": "NODE_ENV=test node --inspect ./node_modules/.bin/_mocha --opts test/mocha.opts test/**/**/**/*.js"
},
"private": true,
"dependencies": {
"express": "3.21.2",
"mongoose": "^4.5.10",
...
},
"devDependencies": {
"chai": "^4.2.0",
"faker": "^4.1.0",
"mocha": "^6.0.0"
}
}
/test/mocha.opts
--recursive
--timeout 30000
--reporter spec
--file ./test/bootstrap.js
/test/bootstrap.js
const mongoose = require('mongoose');
const config = require('./../service/config').getConfig();
mongoose.Promise = global.Promise;
before((done) => {
(async () => {
const connection = await mongoose.connect(config.mongo_url, { useMongoClient: true });
await connection.db.dropDatabase();
})().then(() => {
require('../server');
done();
});
});
after((done) => {
process.kill(process.pid, 'SIGTERM');
done();
});
/server.js
const http = require('http');
const app = require('./app');
const config = require('./service/config');
const port = process.env.PORT || 4000;
const server = http.createServer(app);
server.listen(port, () => {
console.log(`===== Server running:${config.getEnv()}=====`);
});
process.on('SIGTERM', () => {
console.log('===== Server closed =====');
process.exit(0);
});
/test/service/unSubscriber.test.js
const faker = require('faker');
const ContactOptOutRepository = require('../../repository/contactOptOut');
const UnSubscriber = require('../../service/unSubscriber');
const expect = require('chai').expect;
const contactOptOutRepository = new ContactOptOutRepository();
const unSubscriber = new UnSubscriber();
const emails = [
faker.internet.email(),
faker.internet.email(),
faker.internet.email(),
faker.internet.email(),
faker.internet.email(),
];
describe('UnSubscriber', () => {
it('should filter out unsubscribed emails', () => {
return (async () => {
await contactOptOutRepository.newUnSubscription(emails[0], faker.lorem.word());
await contactOptOutRepository.newUnSubscription(emails[1], faker.lorem.word());
await contactOptOutRepository.newUnSubscription(emails[2], faker.lorem.word());
return await unSubscriber.filterUnsubscribed(emails);
})()
.then(filtered => {
expect(filtered.length).to.be.equal(2);
});
});
});