如何断言在 Jest 测试中使用 `async` 调用了依赖项?
How to assert that a dependency was called using `async` in a Jest test?
我有一个服务可以用配置切换的替代行为来装饰异步函数:
// 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;
我有一个 Jest 单元测试,用于验证在相应配置时是否调用了替代行为:
// 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);
});
我想断言,当您使用 await
调用装饰函数时,它也会等待预期的行为。但是,在装饰器中,如果我将 await alternateAsyncFunction();
更改为 alternateAsyncFunction()
,我的单元测试仍然会通过。
如何在单元测试中断言由 addAlternateBehavior()
修饰的函数等待 alternateAsyncFunction
或 originalAsyncFunction
?
为您的 async
函数提供一个在调用内部 mock
之前至少等待两个事件循环周期的实现。然后测试内部 mock
是否被调用:
const decorator = require('./decorator');
const config = require('./config');
it('returned function should use alternate behavior when configured to do so', async () => {
// Arrange
const originalInner = jest.fn();
const originalAsyncFunction = jest.fn(async () => {
await Promise.resolve();
await Promise.resolve();
originalInner();
});
const alternateInner = jest.fn();
const alternateAsyncFunction = jest.fn(async () => {
await Promise.resolve();
await Promise.resolve();
alternateInner();
});
config.useAlternateBehavior = true;
// Act
const decoratedFunction = decorator
.addAlternateBehavior(originalAsyncFunction, alternateAsyncFunction);
await decoratedFunction();
// Assert
expect(originalAsyncFunction.mock.calls.length).toBe(0);
expect(originalInner.mock.calls.length).toBe(0);
expect(alternateAsyncFunction.mock.calls.length).toBe(1);
expect(alternateInner.mock.calls.length).toBe(1);
});
如果 addAlternateBehavior()
创建的函数没有 await
则内部 mock
不会被调用。
请注意,需要两个 await Promise.resolve();
语句,因为第一个语句在 await decoratedFunction();
期间运行的事件循环周期中解析
我有一个服务可以用配置切换的替代行为来装饰异步函数:
// 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;
我有一个 Jest 单元测试,用于验证在相应配置时是否调用了替代行为:
// 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);
});
我想断言,当您使用 await
调用装饰函数时,它也会等待预期的行为。但是,在装饰器中,如果我将 await alternateAsyncFunction();
更改为 alternateAsyncFunction()
,我的单元测试仍然会通过。
如何在单元测试中断言由 addAlternateBehavior()
修饰的函数等待 alternateAsyncFunction
或 originalAsyncFunction
?
为您的 async
函数提供一个在调用内部 mock
之前至少等待两个事件循环周期的实现。然后测试内部 mock
是否被调用:
const decorator = require('./decorator');
const config = require('./config');
it('returned function should use alternate behavior when configured to do so', async () => {
// Arrange
const originalInner = jest.fn();
const originalAsyncFunction = jest.fn(async () => {
await Promise.resolve();
await Promise.resolve();
originalInner();
});
const alternateInner = jest.fn();
const alternateAsyncFunction = jest.fn(async () => {
await Promise.resolve();
await Promise.resolve();
alternateInner();
});
config.useAlternateBehavior = true;
// Act
const decoratedFunction = decorator
.addAlternateBehavior(originalAsyncFunction, alternateAsyncFunction);
await decoratedFunction();
// Assert
expect(originalAsyncFunction.mock.calls.length).toBe(0);
expect(originalInner.mock.calls.length).toBe(0);
expect(alternateAsyncFunction.mock.calls.length).toBe(1);
expect(alternateInner.mock.calls.length).toBe(1);
});
如果 addAlternateBehavior()
创建的函数没有 await
则内部 mock
不会被调用。
请注意,需要两个 await Promise.resolve();
语句,因为第一个语句在 await decoratedFunction();