Sithu
Sithu

Reputation: 4862

Mocha async callback and Sequelize promise are not synchronize?

I'm writing test cases with mocha and its hook beforeEach which deletes and re-creates all tables using sequelize.drop and sequelize.sync.

lib/testutils.js

exports.deleteAll = function () {
    return sequelize.drop({logging: false, cascade: true}).then(function() {
        return sequelize.sync({logging: false});
    });
};

test/controllers/controllers.js

(A) This did work:

var testutils = require("../../lib/testutils");

describe("CRUD Controller", function() {
    beforeEach(function(done) {
        testutils.deleteAll().then(function(){
            done();
        }).catch(function(err) {
            return done(err);
        });
    });

    describe("#read()", function(){
        it("should....", function(done) {
        });
    });
}

(B) This did not work:

var testutils = require("../../lib/testutils");

describe("CRUD Controller", function() {
    beforeEach(function(done) {
        testutils.deleteAll().then(done).catch(function(err) {
            return done(err);
        });
    });

    describe("#read()", function(){
        it("should....", function(done) {
        });
    });
}

I don't understand why testutils.deleteAll().then(done) did not work and the first test case it("should....", function(done) did not wait for the beforeEach hook finished. I was getting TypeError: Converting circular structure to JSON. However, testutils.deleteAll().then(function(){ done(); }) did work.

My question is why (B) is not working while (A) is working? Any idea? Is there something wrong?

Upvotes: 0

Views: 2415

Answers (3)

Oleh Devua
Oleh Devua

Reputation: 384

When you pass done directly it receive object returned from deleteAll, and mocha treat it as an error, so it try apply JSON.stringify to this object and show it as an error, but somehow JSON.stringify can't do it, so it throw exception which you can see. You can clearly see it in Mocha::Runnable#run

Upvotes: 0

ysholqamy
ysholqamy

Reputation: 221

Your deleteAll() function returns sequelize.sync() which returns a promise passing it this. I think the context will be the last model created, so when you pass a function to the returned promise, the function will be passed the last table created. So in case (A) you specified the function() and called done() manually without passing any args to done(). But in case (B) when you pass done to the promise.then(), the last model created will be passed to done.

To get what I mean consider the following:

  User.create({name: 'aName'}).then(function(user){console.log(user)});

is equivalent to

  User.create({name: 'aName'}).then(console.log);

The user will be automatically passed to console.log().

So done was being passed the last model created which I think might cause a problem.

Upvotes: 1

Nilesh Mali
Nilesh Mali

Reputation: 560

Mocha supports promises in beforeEach so just write below code:

beforeEach(function(){
  return testutils.deleteAll();
});

Upvotes: 3

Related Questions