I have a service that can decorate an async function with a configuration-toggled alternate behavior:
// decorator.js
const config = require('./config');
const logger = require('./logger');
function addAlternateBehavior(originalAsyncFunction, alternateAsyncFunction) {
return async () => {
if (config.useAlternateBehavior) {
await alternateAsyncFunction();
} else {
await originalAsyncFunction();
}
logger.info('Behavior finished executing');
};
}
exports.addAlternateBehavior = addAlternateBehavior;
I have a Jest unit test that verifies that the alternate behavior gets called when configured accordingly:
// decorator.test.js
const decorator = require('./decorator');
const config = require('./config');
it('returned function should use alternate behavior when configured to do so', async () => {
// Arrange
const originalAsyncFunction = jest.fn();
const alternateAsyncFunction = jest.fn();
config.useAlternateBehavior = true;
// Act
const decoratedFunction = decorator
.addAlternateBehavior(originalAsyncFunction, alternateAsyncFunction);
await decoratedFunction();
// Assert
expect(originalAsyncFunction.mock.calls.length).toBe(0);
expect(alternateAsyncFunction.mock.calls.length).toBe(1);
});
I want to assert that when you call the decorated function with await, it also awaits the expected behavior. However, in the decorator, if I change await alternateAsyncFunction(); to just alternateAsyncFunction(), my unit test still passes.
How can I assert, in a unit test, that the function decorated by addAlternateBehavior() awaits the alternateAsyncFunction or originalAsyncFunction?
Give your
asyncfunctions an implementation that waits at least two event loop cycles before calling an innermock. Then test if that innermockwas called:If the function created by
addAlternateBehavior()doesn'tawaitthen the innermockwon't get called.Note that two
await Promise.resolve();statements are necessary since the first one resolves during the event loop cycle that runs duringawait decoratedFunction();