chrisdwheatley
chrisdwheatley

Reputation: 137

Testing Express.js res.render within promise with Mocha & Sinon spy

Following a similar pattern to this example I've been attempting to test my routes in an Express.js application but I'm unable to get my spy to verify that res.render has been called when wrapped in a promise.then.

Here's a simplified example where'd I expect calledOnce to be true but it's returning false.

Code under test:

var model = {
  get: function() {
    return new Promise(function(res, rej) {
      return res('success');
    });
  }
};

module.exports = function (req, res) {
  model.get().then(function (data) {
    res.render('home', data);
  }).catch(function (err) {
    console.log(err);
  });
};

Test:

var expect = require('chai').expect;
var sinon = require('sinon');
var home = require('./home');

describe('home route', function() {
  it('should return a rendered response', function() {
    var req = {};

    var res = {
      render: sinon.spy()
    };

    home(req, res);

    expect(res.render.calledOnce).to.be.true;
  });
});

Upvotes: 0

Views: 3418

Answers (1)

robertklep
robertklep

Reputation: 203359

You have to wait for the promise to get resolved, which is an asynchronous operation.

Since Mocha supports promises natively, you can set up your code to pass the original promise all the way back to Mocha, and insert a test case in the chain:

// home.js
...
module.exports = function (req, res) {
  // return the promise here
  return model.get().then(function (data) {
    res.render('home', data);
  }).catch(function (err) {
    console.log(err);
  });
};

// test.js
describe('home route', function() {
  it('should return a rendered response', function() {
    var req = {};
    var res = { render: sinon.spy() };

    // Also return the promise here, and add an assertion to the chain.
    return home(req, res).then(function() {
      expect(res.render.calledOnce).to.be.true;
    });
  });
});

Upvotes: 3

Related Questions