lundi 1 février 2016

Timing for testing express controllers with sinon

I am trying to write unit tests for an Express REST API and I'm using Sinon to spy on my response object. But I'm having some timing issues that I can't seem to get around.

Code:

My controller looks like this (app_api/controllers/vendors.js):

var Vendor = mongoose.model('Vendor');

module.exports.vendorsCreateOne = function (req, res) {
  Vendor.create({
    "name": req.body.name
  }, function (err, vendor) {
    res.status(201);
    res.json(vendor);
    console.log("CTRL: " + res);
  });
};

And my test looks like this (test/unit/vendorControllers.spec.js):

describe("Vendor Controllers", function() {

  var vendorsCreateOne = require('../../app_api/controllers/vendors').vendorsCreateOne;
  var req, res

  beforeEach(function(done) {
    req = res = {};
    res.status = sinon.spy();
    res.json = sinon.spy();
    done();
  });

  describe("CreateOne", function () {

    it("responds only once", function () {
      req.body = {"name": "hi"};
      vendorsCreateOne(req, res);
      console.log("TEST: " + res);
      expect(res.status.calledOnce).to.equal(true);
    });

  });

};

Please note the console.log()s in the code above, they will highlight the problem.

Problem:

When I run this test it fails with the following output:

    Vendor Controllers
      CreateOne
TEST: [object Object]
      1) should respond only once
CTRL: [object Object]

  1 failing

  1) Vendor Controllers CreateOne responds only once:

     AssertionError: expected false to equal true
     + expected - actual

     -false
     +true

The test is failing because res.status never gets called. As you can see from the logs, the test finishes running before the controller.

Question:

Is there any way I can rewrite this to force the test to run after the controller?

Aucun commentaire:

Enregistrer un commentaire