web-dev-qa-db-fra.com

Moka avantChaque vs avant exécution

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?

44
Tomo

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.

54
Steven Scott

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.

23
Tomasz Wszelaki

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 .

10
Victor Perov

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);
      });
  });
});


0
ivan.proskuryakov