I am dealing with a code mixing node-style callbacks and Bluebird promises, and I need to write some unit tests for it.
In particular, cache.js
exposes the init()
function, which works with promises. It is then called by the doSomething()
function in another file (e.g. index.js
) which in turn accepts a callback that has to be invoked at the end of init()
.
Pseudocode is as follows:
// [ cache.js ]
function init() {
return performInitialisation()
.then((result) => return result);
}
// [ index.js ]
var cache = require('./cache');
function doSomething(callback) {
console.log('Enter');
cache.init()
.then(() => {
console.log('Invoking callback');
callback(null);
})
.catch((err) => {
console.log('Invoking callback with error');
callback(err);
});
console.log('Exit');
}
A possible unit test could be (showing only relevant code):
// [ index.test.js ]
...
var mockCache = sinon.mock(cache);
...
it('calls the callback on success', function(done) {
mockCache.expects('init')
.resolves({});
var callback = sinon.spy();
doSomething(callback);
expect(callback).to.have.been.calledOnce;
done();
});
This test passes, however changing the expectation to not.have.been.calledOnce
also passes, which is wrong.
Also, console logs are out of sequence:
Enter
Exit
Invoking callback
I have looked at several possibilities, none of which worked:
Using chai-as-promised, e.g.
expect(callback).to.eventually.have.been.calledOnce;
Refactoring
doSomething()
to be simply:function doSomething(callback) { cache.init() .asCallback(callback); }
Can anyone help me understand what I am doing wrong and how I can fix it please?