Mocha beforeEach vs before execution

后端 未结 4 1213
死守一世寂寞
死守一世寂寞 2020-12-24 04:42

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 li

相关标签:
4条回答
  • 2020-12-24 05:25

    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.

    0 讨论(0)
  • 2020-12-24 05:25

    The key thing is to have mocha.opts file with the line pointing on ./test/bootstrap.js, where you apply before, beforeAll, after, afterAll hooks.

    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 flag for debugging


    /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 讨论(0)
  • 2020-12-24 05:34

    The reason of confusion is lies in the documentation of mocha. You can find in 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).

    Discussed hooks before and beforeEach are executed right before all or each it respectively - there are no way to execute it before describe section.

    Here you can find answer of the #1 contributor to the mocha's master branch to the idea add something like beforeDescribe hook.

    I think you should look at the --delay mocha option.

    0 讨论(0)
  • 2020-12-24 05:41

    Mocha's test runner explains this functionality the best in the Hooks section of the Mocha Test Runner.

    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.

    0 讨论(0)
提交回复
热议问题