如何测试一个函数是否在等待,不仅被调用?

时间:2019-05-16 03:01:10

标签: javascript jestjs

考虑测试以下简化功能

const functionToBeTested = async (val) => {
    await otherModule.otherFunction(val/2);
}

在开玩笑的测试中,我想确保otherModule.otherFunction不仅被调用而且还在等待。换句话说,我想编写一个测试,如果有人从await前面删除otherFunction,则该测试将失败。

我到目前为止有这个

test('should wait on otherFunction', () => {
   await functionToBeTested(6) 
   expect(otherModule.otherFunction).toHaveBeenCalledWith(3);  
}

但是expect(otherModule.otherFunction).toHaveBeenCalledWith(3);检查并不能验证functionToBeTested是否在otherFunction上等待。

2 个答案:

答案 0 :(得分:1)

这是我想出的:

const delay = duration => new Promise(resolve => setTimeout(resolve, duration));

test('should wait on otherFunction', async () => {
  let resolve;
  const mockPromise = new Promise((res) => {resolve = res;});
  otherModule.otherFunction.mockReturnValue(mockPromise);
  const resolution = jest.fn();

  functionToBeTested(6).then(resolution);

  expect(otherModule.otherFunction).toHaveBeenCalledWith(3);
  await delay(0);
  expect(resolution).not.toHaveBeenCalled();
  resolve();
  await delay(0);
  expect(resolution).toHaveBeenCalled();
}

因此,我嘲笑otherFunction返回未解决的promise,但是我可以在测试期间随意解决。然后,我调用要测试的函数,并在完成时给其回调。

然后我想断言它没有调用回调,但是由于Promise解析始终是异步的,因此我需要添加超时0以使Promise可以解决。我选择使用承诺版本的setTimeout来做到这一点。

最后,我解析了mockPromise,将超时设置为0(再次,以确保promise有机会调用其回调),并断言现在已经调用了决议 。 / p>

答案 1 :(得分:0)

如果您无法检查otherModule.otherFunction的解析值或任何副作用,则无需测试解析的值。

否则,在以下示例中删除await将导致测试失败。

describe('check for side effect', () => {
    let sideEffect = false;

    const otherModule = {
        otherFunction: x =>
            new Promise(resolve => {
                setTimeout(() => {
                    sideEffect = true;
                    resolve();
                }, 0);
            }),
    };

    const functionToBeTested = async val => {
        await otherModule.otherFunction(val / 2);
    };

    test('should wait on otherFunction', async () => {
        const spy = jest.spyOn(otherModule, 'otherFunction');

        await expect(functionToBeTested(6)).resolves.toBeUndefined();
        expect(spy).toHaveBeenCalledWith(3);
        expect(sideEffect).toBe(true);
    });
});

describe('check returned value', () => {
    const otherModule = {
        otherFunction: x =>
            new Promise(resolve => {
                setTimeout(() => {
                    resolve('hello');
                }, 0);
            }),
    };

    const functionToBeTested = async val => {
        const res = await otherModule.otherFunction(val / 2);
        return `*** ${res} ***`;
    };

    test('should wait on otherFunction', async () => {
        const spy = jest.spyOn(otherModule, 'otherFunction');

        const promise = functionToBeTested(6);
        expect(spy).toHaveBeenCalledWith(3);
        await expect(promise).resolves.toBe('*** hello ***');
    });
});