无法在mocha测试的上下文中使用调用带有promise的方法调用sinon间谍

时间:2016-05-22 08:21:06

标签: javascript node.js unit-testing mocha sinon

我有一个调用使用bluebird promises的方法的模块。这是模块,简化。 Cassandra只是一些能够满足它们的db调用的包装器:

var Cassandra = require('../lib/cassandraObject');
var cassandra = new Cassandra();
exports.doIt = function _doIt(req, res) {
    cassandra.queryPromise("query", [1, 2, 3])
    .then(function (results) {
        res.sendStatus(200);
     })
    .catch(function(er) {
        res.sendStatus(500);
    })
}

我试图用sinon和sinon-bluebird测试这个。我为Cassandra的查询承诺存根,并且让res.sendStatus成为间谍:

   it("makes a call to doIt", function () {
        var qpMock = sinon.stub(Cassandra.prototype, "queryPromise").resolves(['yay!']);
        var req = {};
        var res = {
            sendStatus: sinon.spy(),
        };
        myModule.doIt(req, res);
        expect(qpMock.args[0][1][0]).to.equal(1);   //ok
        expect(res.sendStatus).to.have.been.calledWith(200);  //error ! not called yet!
    }

我认为使用这些库时,会立即调用存根的then(),而不是异步调用,但似乎并非如此。 res.sendStatus()调用确实被调用,但是在测试超出范围之后。

有没有办法知道何时调用res.sendStatus()并将其保留在测试范围内,以便我可以断言传递给它的值?

1 个答案:

答案 0 :(得分:2)

我建议让doIt()链接,让它返回承诺:

exports.doIt = function _doIt(req, res) {
    return cassandra.queryPromise("query", [1, 2, 3])
                    .then(function (results) {
                      res.sendStatus(200);
                    })
                    .catch(function(er) {
                      res.sendStatus(500);
                    })
}

这样,您可以等待测试用例完成,以便在确定已被调用时检查res.sendStatus()

此外,由于Mocha支持开箱即用的承诺,您可以从doIt()返回承诺,以确保Mocha在继续之前等待您的测试完全完成:

it("makes a call to doIt", function () {
  var qpMock = sinon.stub(Cassandra.prototype, "queryPromise").resolves(['yay!']);
  var req = {};
  var res = { sendStatus: sinon.spy() };
  return myModule.doIt(req, res).then(() => {
    expect(qpMock.args[0][1][0]).to.equal(1); 
    expect(res.sendStatus).to.have.been.calledWith(200);
  });
})