node.js 摩卡 beforeEach 与执行前
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32660241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mocha beforeEach vs before execution
提问by Tomo
I ran into a problem recently that I can't explain. I have alot of code in these tests so I'm going to do my best to capture the idea here
我最近遇到了一个我无法解释的问题。我在这些测试中有很多代码,所以我将尽我所能在这里捕捉这个想法
I have tests that look like:
我的测试看起来像:
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
});
});
});
The problem is, the beforeEach by #1runs fine. I can see it happening on the DB and the tests in #2pass.
问题是, beforeEach by#1运行良好。我可以看到它发生在数据库和通过的测试中#2。
However, the tests in the preferences context at #4fail because it cant find the user to log them in at #3.
但是,首选项上下文中的测试#4失败,因为它无法找到用户登录#3。
It seems that the context beforeis executed before the describe beforeEach, which causes them to fail. If I move logUserIninto the itblock it works fine.
似乎上下文before在 describe 之前执行beforeEach,这导致它们失败。如果我移动logUserIn到it块正常工作。
What could cause this?
什么可能导致这种情况?
回答by Steven Scott
Mocha's test runner explains this functionality the best in the Hooks section of the Mocha Test Runner.
Mocha 的测试运行器在 Mocha 测试运行器的Hooks 部分对这个功能进行了最好的解释。
From the Hooks section:
从钩子部分:
describe('hooks', function() {
before(function() {
// runs before all tests in this file regardless where this line is defined.
});
after(function() {
// runs after all tests in this file
});
beforeEach(function() {
// runs before each test in this block
});
afterEach(function() {
// runs after each test in this block
});
// test cases
});
You can nest these routines within other describe blocks which can also have before/beforeEach routines.
您可以将这些例程嵌套在其他描述块中,这些块也可以具有 before/beforeEach 例程。
回答by Tomasz Wszelaki
I found a similar issue. The documentation is misleading because "before this block" means (to me at least) "before this describe section". Meanwhile it means "before any describe section". Check this example:
我发现了一个类似的问题。该文档具有误导性,因为“在此块之前”意味着(至少对我而言)“在此描述部分之前”。同时它的意思是“在任何描述部分之前”。检查这个例子:
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
It seems it doesn't matter where in your hierarchy you put the before- it will run before any describe and not before its containing describe.
似乎在您的层次结构中放置的位置无关紧要before- 它会在任何描述之前运行,而不是在其包含描述之前运行。
回答by Victor Perov
The reason of confusion is lies in the documentation of mocha. You can find in mocha:
混淆的原因在于 mocha 的文档。你可以在mocha 中找到:
Tests can appear before, after, or interspersed with your hooks. Hooks will run in the order they are defined, as appropriate; all before() hooks run (once), then any beforeEach() hooks, tests, any afterEach() hooks, and finally after() hooks (once).
测试可以出现在您的钩子之前、之后或穿插其中。钩子将按照它们定义的顺序运行,视情况而定;所有 before() 钩子运行(一次),然后是任何 beforeEach() 钩子,测试,任何 afterEach() 钩子,最后是 after() 钩子(一次)。
Discussed hooks beforeand beforeEachare executed right before all or each itrespectively - there are no way to execute it before describesection.
讨论的钩子before和beforeEach分别在 all 或 each 之前执行it- 在描述部分之前无法执行它。
Here you can findanswer of the #1 contributor to the mocha's master branch to the idea add something like beforeDescribehook.
在这里,您可以找到mocha 主分支的#1 贡献者的答案,以添加类似beforeDescribe钩子的想法。
I think you should look at the --delaymocha option.
我认为你应该看看--delaymocha选项。
回答by Ivan Proskuryakov
The key thing is to have mocha.optsfile with the line pointing on ./test/bootstrap.js, where you apply before, beforeAll, after, afterAll hooks.
关键是让mocha.opts文件的行指向./test/bootstrap.js,您可以在其中应用 before、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 --inspectflag for debugging
node --inspect调试标志
/package.json
/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
/test/mocha.opts
--recursive
--timeout 30000
--reporter spec
--file ./test/bootstrap.js
/test/bootstrap.js
/测试/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
/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
/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);
});
});
});

