首页 > 解决方案 > React/Jest/Enzyme - 等待时间不够长

问题描述

我有一个等待多个承诺的功能

const function = async () => {
    await function1()
    await function2()
    await function3()
}

我想测试调用了 function3:

it(('calls function3', async () => {
    jest.spyOn(api, 'function1').mockResolvedValue({})
    jest.spyOn(api, 'function2').mockResolvedValue({})
    spy = jest.spyOn(api, 'function3')
    await function()
    expect(spy).toBeCalledTimes(1)
})

这个测试失败了,但是当我多次调用 await 时:

it(('calls function3', async () => {
    jest.spyOn(api, 'function1').mockResolvedValue({})
    jest.spyOn(api, 'function2').mockResolvedValue({})
    spy = jest.spyOn(api, 'function3')
    await await await await await function()
    expect(spy).toBeCalledTimes(1)
})

测试将通过。为什么是这样?await function()在进入下一个期望行之前不应该解决所有的承诺吗?

编辑:awaited 函数越深,即 function4,我需要的 await 语句越多,但不是 1 比 1。

标签: javascriptreactjsecmascript-6jestjsenzyme

解决方案


await function()在进入下一个期望行之前不应该解决所有的承诺吗?

是的,await将等待返回Promise后再继续。

这是一个简单的工作示例:

const function1 = jest.fn().mockResolvedValue();
const function2 = jest.fn().mockResolvedValue();
const function3 = jest.fn().mockResolvedValue();

const func = async () => {
  await function1();
  await function2();
  await function3();
}

it('calls function3', async () => {
  await func();
  expect(function3).toHaveBeenCalled();  // Success!
})

如果await没有像预期的那样等待,那么Promise链条很可能在某个时候被打破了。

下面是一个Promise断链的例子:

const function1 = jest.fn().mockResolvedValue();
const function2 = jest.fn().mockResolvedValue();
const function3 = jest.fn().mockResolvedValue();

const func = async () => {
  await function1();
  await function2();
  await function3();
}

const func2 = async () => {
  func();  // <= breaks the Promise chain
}

it('calls function3', async () => {
  await func2();
  expect(function3).toHaveBeenCalled();  // <= FAILS
})

await多次调用会将其余的测试函数多次排队在PromiseJobs队列的后面,这可以给挂起Promise的回调一个运行的机会......

...因此,如果将其更改为以下内容,上面的损坏测试将通过:

it('calls function3', async () => {
  await await await await func2();  // <= multiple await calls
  expect(function3).toHaveBeenCalled();  // Success...only because of multiple await calls
})

...但真正的解决方案是找到并修复Promise断链的位置:

const func2 = async () => {
  await func();  // <= calling await on func fixes the Promise chain
}

it('calls function3', async () => {
  await func2();
  expect(function3).toHaveBeenCalled();  // Success!
})

推荐阅读