Mocha: Mocha does not run tests defined within a function

Created on 23 Apr 2018  路  5Comments  路  Source: mochajs/mocha

Prerequisites

  • [x] Checked that your issue hasn't already been filed by cross-referencing issues with the faq label
  • [x] Checked next-gen ES issues and syntax problems by using the same environment and/or transpiler configuration without Mocha to ensure it isn't just a feature that actually isn't supported in the environment in question or a bug in your code.
  • [x] 'Smoke tested' the code to be tested by running it outside the real test suite to get a better sense of whether the problem is in the code under test, your usage of Mocha, or Mocha itself
  • [x] Ensured that there is no discrepancy between the locally and globally installed versions of Mocha. You can find them with: node node_modules/.bin/mocha --version(Local) and mocha --version(Global). We recommend avoiding the use of globally installed Mocha.

Description

I am trying to test my API with mocha & superagent, the thing is, I need to wait for the db to open, then export the app, because the tests require some initialization code that depends on the db.

So, in order to do that, I had to wrap my test code within an async function and call it, but it doesn't run the tests.

// test.js

describe('math', async () => {
  it('multiplies', () => {
    let result = 2 * 2;
    result.should.equal(4);
  });
});

const test = async () => {
  const should = require('chai').should();
  const request = require('supertest');
  const path = require('path')
  const app = await require(path.resolve('./server'));


  describe('math', async () => {
    it('adds', () => {
      let sum = 1 + 1;
      sum.should.equal(2);
    });
  });

  describe('users', async () => {
    it('creates a customer', async () => {
      let res = await request(app).get('/api/should-404/');
      res.status.should.equal(200);
    });
  });
};

test().catch(console.err);
// server.js

const run = async () => {
  const app = express()();
  const mongoose = require('mongoose');
  await mongoose.connect('mongodb://localhost:27017/speero_test');

  const db = mongoose.connection;

  db.on('error', console.error.bind(console, 'connection error:'));
  db.once('open', () => {console.log.bind(console, 'connection :')});

  // the line below depends on the db
  const initRolesPolicies = require(path.resolve('./initialize/initPolicies'))();

  app.listen(port, function () {
    console.log('Autotash is running ' + process.env.NODE_ENV.toUpperCase() + ' on port ' + port + ' !');
  });

  return app;
}

module.exports = run().catch(console.err);

Steps to Reproduce

Expected behavior: All tests to run, the multiplication, the addition, and the customer creation.

Actual behavior: Only the multiplication test (the one outside the _test function_) run, the ones inside are completely ignored even though I execute the function at the bottom.

I don't completely like wrapping the test suites inside a function, but I have to await for the app to be returned, I am open for any other approaches to accomplish this. I just need to wait for db to be ready before exporting the app object and running the tests.

Reproduces how often: [100%]

Versions

  • mocha v4.0.1
  • node v8.9.3
  • mongoose v5.0.14
  • Windows 10
  • Cmder

Most helpful comment

yep what you have now is good, that is a very common pattern with Mocha. Note that I made a correction to my previous statement. Let me explain better:

// this is bad
describe('foo', async _ => {
    it('bar', async done => {
    });
});
// this is good
describe('foo',  _ => {   // remove async from here
    it('bar', async done => {
    });
});

All 5 comments

First thing I notice:

const test = async () => {  // not OK =>  using async function...not kosher in this case
   // ...

  describe('math', async () => {   // this is NOT OK either
    it('adds', () => {
      let sum = 1 + 1;
      sum.should.equal(2);
    });
  });

 // ....
};

you shouldn't register any of the following asynchronously:

it/describe/before/after/afterEach/beforeEach, etc.

all hooks should be registered synchronously, otherwise you will get unknown/undefined behavior.

What if I need to do some async functions on before and beforeEach, like cleaning the database for example?

How should I handle that?

Edit:
I misunderstood. I should write the describe(...) outside an asynchronous function, however, what I write inside the describe(...) can be async.

Actually, I think I just found a solution!

// test.js

const should = require('chai').should();
const request = require('supertest');
const path = require('path')
let app;

before(async () => {
  try {
    app = await require(path.resolve('./server'));
  }
  catch (err) {
    console.log(err);
  }
});

describe('math', async () => {
  it('multiplies', () => {
    let result = 2 * 2;
    result.should.equal(4);
  });
  it('adds', () => {
    let sum = 1 + 1;
    sum.should.equal(2);
  })
});

describe('users', async () => {
  it('creates a customer', async () => {
    let res = await request(app).get('/api/should-404/');
    res.status.should.equal(200);
  });
});

This did the trick after two days of trying to figure it out.

I am completely new to testing, is there a better way to do this?

yep what you have now is good, that is a very common pattern with Mocha. Note that I made a correction to my previous statement. Let me explain better:

// this is bad
describe('foo', async _ => {
    it('bar', async done => {
    });
});
// this is good
describe('foo',  _ => {   // remove async from here
    it('bar', async done => {
    });
});

Thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings