J'ai rencontré récemment un problème que je ne peux pas expliquer. J'ai beaucoup de code dans ces tests, donc je vais faire de mon mieux pour capturer l'idée ici
J'ai des tests qui ressemblent à:
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
});
});
});
Le problème est que le beforeEach by #1
fonctionne bien. Je peux le voir se passer sur la base de données et les tests dans #2
passer.
Cependant, les tests dans le contexte des préférences à #4
échoue car il est impossible de trouver l’utilisateur qui se connecte à #3
.
Il semble que le contexte before
soit exécuté avant le describe beforeEach
, ce qui entraîne leur échec. Si je déplace logUserIn
dans le bloc it
cela fonctionne très bien.
Qu'est-ce qui pourrait causer ça?
Le testeur de Mocha explique cette fonctionnalité au mieux dans la section Crochets du testeur de Mocha .
De la section des crochets:
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
});
Vous pouvez imbriquer ces routines dans d'autres blocs décris qui peuvent également avoir des routines before/beforeEach.
J'ai trouvé un problème similaire. La documentation est trompeuse car "avant ce bloc" signifie (du moins pour moi) "avant cette section de description". En attendant, cela signifie "avant toute section de description". Vérifiez cet exemple:
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
Il semble que peu importe où vous mettez le before
dans votre hiérarchie - il sera exécuté avant toute description et pas avant sa description contenant.
La raison de la confusion réside dans la documentation du moka. Vous pouvez trouver dans moka :
Les tests peuvent apparaître avant, après ou parsemés de vos crochets. Les crochets courent dans l'ordre dans lequel ils ont été définis, le cas échéant; tous les crochets before () sont exécutés (une fois), puis tous les crochets beforeEach (), les tests, tous les crochets afterEach () et enfin les crochets after () (une fois).
Les hooks discutés before
et beforeEach
sont exécutés juste avant tout ou chaque it
respectivement - il n’existe aucun moyen de l’exécuter avant decrire section.
Ici vous pouvez trouver la réponse du # 1 contributeur à la branche principale du moka à l'idée d'ajouter quelque chose comme beforeDescribe
hook.
Je pense que vous devriez regarder le --delay
moka option .
L'essentiel est d'avoir mocha.opts
fichier avec la ligne pointant sur ./test/bootstrap.js
, où vous appliquez avant, avant, après, après, après tous les crochets.
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
drapeau pour le débogage
/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);
});
});
});