【问题标题】:How to test whether a function was waited on, not only called?如何测试一个函数是否被等待,而不仅仅是被调用?
【发布时间】:2019-05-16 03:01:10
【问题描述】:

考虑测试以下简化函数

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

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

到目前为止我有这个

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

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

【问题讨论】:

  • 您能否检查第一个值是否不是调用第二个函数时应有的值,然后在调用第二个函数后再次检查它
  • 干脆不要测试它是否完成,它是实现细节,或者你有一个具体的用例?
  • Answered here for MochaSinon...同样的概念也适用于使用 Jest

标签: javascript jestjs


【解决方案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 以返回一个未解决的承诺,但我可以在测试期间随意解决它。然后我调用我想要测试的函数,并在它完成时给它一个回调。

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

最后,我解决了 mockPromise,执行超时 0(再次确保 Promise 有机会调用其回调),并断言现在解决方案被调用。

【讨论】:

    【解决方案2】:

    如果您无法检查 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 ***');
        });
    });
    

    【讨论】:

      猜你喜欢
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-26
      • 2022-10-25
      • 1970-01-01
      • 2016-08-07
      相关资源
      最近更新 更多