When testing callback based code, we can create fakes that yield (e.g. sinon.fake.yield(null, "result")), and we can also programatically invoke the callback somewhere in a test (e.g. myFake.callback(null, "result")).
When testing promise based code, we only have the first option with sinon.fake.resolves("result"), and there is no convenient way to have a fake return a promise and control when it is invoked.
I'm currently helping myself with something like this:
const resolver = sinon.fake();
const promise = new Promise(resolver);
const fake = sinon.fake.returns(promise);
// trigger something
resolver.firstCall.firstArg("result");
await promise;
Here is an example using fakes, but this would work the same way with stubs:
const promise = sinon.promise();
const fake = sinon.fake.returns(promise);
// trigger something
await promise.resolve("result");
The sinon promise could be a regular promise and expose these additional functions:
resolve(value)reject(value)and these properties:
resolvedValuerejectedValuePlease let me know your thoughts.
This seems like a great addition
I don't understand the examples ...
Here is a simple, runnable example:
'use strict';
const fs = require('fs/promises');
async function readPackageJson() {
const json = await fs.readFile('package.json', 'utf8');
return JSON.parse(json);
}
// ----------------------------------------------------------------
const assert = require('assert');
const sinon = require('sinon');
describe('readPackageJson', () => {
afterEach(() => {
sinon.restore();
});
it('reads package.json before invoking JSON.parse with result', async () => {
const resolver = sinon.fake();
const promise = new Promise(resolver);
sinon.replace(fs, 'readFile', sinon.fake.returns(promise));
sinon.replace(JSON, 'parse', sinon.fake.returns({}));
readPackageJson();
sinon.assert.calledWith(fs.readFile, 'package.json', 'utf8');
sinon.assert.notCalled(JSON.parse);
const json = '{"version":"1.0.0"}';
// The following causes the promise to resolve and the await to complete in the implementation.
// It would read nicer as `await promise.resolve(json)`.
resolver.firstCall.firstArg(json);
await promise;
sinon.assert.calledWith(JSON.parse, json);
});
});
Now I get it. Thank you!
Most helpful comment
Here is a simple, runnable example: