I'm trying to understand how to best unit test my asynchronous CommonJS modules. I'm struggling to understand best practice when dealing with multiple chained promises.
Lets assume I have the following module defined:
module.exports = function(api, logger) {
return api.get('/foo')
.then(res => {
return api.post('/bar/' + res.id)
})
.then(res => {
logger.log(res)
})
.catch(err => {
logger.error(err)
})
}
and I have the following spec file trying to test that the correct calls are made.
var module = require('./module')
describe('module()', function() {
var api;
var logger;
var getStub;
var postStub;
beforeEach(function() {
getStub = sinon.stub();
postStub = sinon.stub();
api = {
get: getStub.resolves({id: '123'),
post: postStub.resolves()
}
logger = {
log: sinon.spy(),
error: sinon.spy()
}
})
afterEach(function() {
getStub.restore();
postStub.restore();
});
it('should call get and post', function(done) {
module(api, logger) // System under test
expect(getStub).to.have.been.calledWith('/foo')
expect(postStub).to.have.been.calledWith('/bar/123')
done()
})
})
This doesn't work. The first assertion passes correctly, but the second assertion fails, as presumably the promise hasn't resolved at the time of execution.
I can fix this using process.nextTick or setTimeout but I'd like to see how other people have solved this more gracefully.
I've tried adding chai-as-promised into the mix with little luck. My current setup includes, sinon, chai, sinon-as-promised and sinon-chai.
Thanks
You should use the fact that module()
returns a promise, so you can add another .then()
to the chain where you can assert the arguments (because at that point the previous .then()
steps have been called, including the call to api.post()
).
And since Mocha supports promises, you can return the resulting promise instead of having to deal with done
:
it('should call get and post', function() {
return module(api, logger).then(() => {
expect(getStub).to.have.been.calledWith('/foo')
expect(postStub).to.have.been.calledWith('/bar/123')
});
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With