Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I factor out common before() calls with mocha?

I have a lot of duplication in my mocha tests:

describe("Some test", function() {
    before(helpers.testPrepare);
    beforeEach(helpers.freshDB);

    it("should foo", function(done) {
        //...
        done();
    });

    after(helpers.teardownServer);
});

describe("Another test", function() {
    before(helpers.testPrepare);
    beforeEach(helpers.freshDB);

    it("should bar", function(done) {
        //...
        done();
    });

    after(helpers.teardownServer);
});

This could cause problems if I forget to call beforeEach and it's a pain to refactor. I'd like to define a describe that ensures I always call my setup and teardown, so I can just write:

I would like to write this as:

var describe = require('./helpers').describe;

describe("Some test", function() {
    it("should foo", function(done) {
        //...
        done();
    });
});

How can I do this, since mocha is defining describe as a global? How do I ensure everything is executed in the right order?

like image 490
Wilfred Hughes Avatar asked Mar 17 '23 14:03

Wilfred Hughes


2 Answers

I would create a helpers.js file that contains this:

function beforeEachExample() { console.log("before each"); }

function beforeExample() { console.log("before"); }

function afterExample() { console.log("after"); }

function makeSuite(desc, cb) {
    describe(desc, function () {
        before(beforeExample);
        beforeEach(beforeEachExample);

        cb();

        after(afterExample);
    });
}

exports.makeSuite = makeSuite;

And then I could have test/something.js:

var makeSuite = require("../helpers").makeSuite;

makeSuite("something", function () {
    it("one", function () {});
    it("two", function () {});
});

And test/somethingelse.js:

var makeSuite = require("../helpers").makeSuite;

makeSuite("something else", function () {
    it("one", function () {});
    it("two", function () {});
});

Running the setup above gives:

$ mocha

  something
before
before each
    ✓ one 
before each
    ✓ two 
after

  something else
before
before each
    ✓ one 
before each
    ✓ two 
after

  4 passing (5ms)
like image 173
Louis Avatar answered Mar 31 '23 18:03

Louis


You can compose describe blocks within each other. So now you can do . . .

describe('Database Tests', function () {
  before(helpers.testPrepare);
  beforeEach(helpers.freshDB);

  describe('Some test', function () {
   it('should foo', function (done) {
    done();
   });
  });

  describe('Another test', function () {
   it('should bar', function (done) {
     done();
   });
  });
});

EDIT: In regards to your comment you might try creating a module as such.

harness.js
module.exports.beforeHooks = function () {
 before(hlepers.testPrepare);
 beforeEach(helpers.freshDB);
}

and then do this ...

var harness = require('./harness.js');
describe('Database Tests', function () {
  harness.beforeHooks();

It might not work because the scoping is all messed up, but if that's the case you can pass those functions in your beforeHooks functions.

module.exports.beforeHooks(before, beforeEach)

and call it like before, but pass those functions in as objects like so.

harness.beforeHooks(before, beforeEach);
like image 41
Breedly Avatar answered Mar 31 '23 19:03

Breedly