如何断言在Jest测试中使用`async`调用了依赖项?

时间:2018-08-17 20:25:38

标签: javascript promise async-await jestjs assertions

我有一项服务,可以通过配置触发的替代行为来装饰异步功能:

// 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()装饰的函数正在等待alternateAsyncFunctionoriginalAsyncFunction

1 个答案:

答案 0 :(得分:1)

赋予您的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();的事件循环周期内会解决