I have an async function f that calls another async function g. To test if f calls g, I'm stubbing g using sinon and assert it's been called using should.js.
'use strict';
require('should-sinon');
const sinon = require('sinon');
class X {
async f(n) {
await this.g(n);
// this.g(n); // I forget to insert `await`!
}
async g(n) {
// Do something asynchronously
}
}
describe('f', () => {
it('should call g', async () => {
const x = new X();
sinon.stub(x, 'g').resolves();
await x.f(10);
x.g.should.be.calledWith(10);
});
});
But this test passes even when I forget to use await when calling g in f.
One of the ways to catch this error is to make the stub return a dummy promise and check if its then is called.
it('should call g', async () => {
const x = new X();
const dummyPromise = {
then: sinon.stub().yields()
};
sinon.stub(x, 'g').returns(dummyPromise);
await x.f(10);
x.g.should.be.calledWith(10);
dummyPromise.then.should.be.called();
});
But this is a bit bothersome. Are there any convenient ways to do this?
Your example for
fshows flawed code design which becomes more obvious if you write the same function withoutasync/awaitsyntax:f(n) { return g(n).then(()=>{}); }This achieves the same behavior - whether
gresolved becomes hard to tell (assuming you don't know iffreturnedg's promise, which is the same as not knowing whetherfawaitedg). Iffis not interested in the result ofgit should just simply return it, not hide it. Then you can simply test for the result.If your point is that
fmight have to trigger severalasynccalls sequentiallyawaiting severalg_1,g_2,... to resolve, then you can build a test chain by asserting in the stub ofg_n+1that the dummy-promise ofg_nhas been resolved. In general your approach to test a dummy-promise for its status is fine.