【问题标题】:Test failing after adding then and catch to promise添加 then 后测试失败并捕获承诺
【发布时间】:2019-08-16 16:18:52
【问题描述】:

我有以下代码(为了缩小问题范围而进行了简化):

function pushPromises() {
  const promises = [];

  promises.push(firstPromise('something'))
  promises.push(secondPromise('somethingelse'))

  return promises;
}

export default handlePromises(async (c) => {
  const results = await Promise.all(pushPromises())
  c.success(results);
});

我的测试模拟了那些 firstPromise 和 secondPromise 以检查它们是否被正确的参数调用。这有效(假设模拟设置已正确完成):

jest.mock('src/firstPromise');
jest.mock('src/secondPromise');

describe('test', () => {
  let firstMock;
  let secondMock;


  beforeEach(() => {
    require('src/firstPromise').default = firstMock;
    require('src/secondPromise').default = secondMock;
  })

  it('test', async () => {
    await handlePromises(context);
    expect(firstPromiseMock).toHaveBeenCalledTimes(1);
    expect(secondPromiseMock).toHaveBeenCalledTimes(1);
  });
});

现在,如果我向 Promise 添加处理程序,例如:

function pushPromises() {
      const promises = [];

      promises.push(
        firstPromise('something')
        .then(r => console.log(r))
        .catch(e => console.log(e))
      )
      promises.push(
        secondPromise('somethingelse')
        .then(r => console.log(r))
        .catch(e => console.log(e))
      )

      return promises;
    }

第一个期望通过,但第二个没有。看起来第二个 promise 不再被调用。

如何修改测试/代码,以便在 Promise 上添加处理程序不会导致测试中断?看起来它只是在第一个 Promise 处理程序上完成执行,并且永远不会到达第二个。

编辑:

我已修改函数以返回 Promise.all 而无需等待:

 export default handlePromises(async (c) => {
      return Promise.all(pushPromises())
 });

但我遇到了完全相同的问题。如果第一个 promise 有 .then,则不会调用第二个 promise。

【问题讨论】:

  • 这些模拟是如何设置的?
  • await handlePromises(context);handlePromises 对我来说不像是一个承诺,所以 await 不会有任何效果。
  • handlePromises(context) 这里 context 必须有一个名为 success 的回调,然后你必须将你的期望语句移动到成功回调中。
  • 您有两种非常不同的方式调用handlePromises。在您的真实代码中,您使用异步函数调用它并导出它的结果,很可能是一个承诺。在您的测试代码中,您使用上下文调用它,这很可能是一个对象。
  • 添加了模拟设置@raina77ow

标签: javascript promise mocking jestjs


【解决方案1】:

您的 handlePromises 函数接受回调,但您正在处理它,因为它返回一个承诺,这不是一个好方法,但您可以使用回调测试您的方法,如下所示

将您的测试修改为=>

it('test', (done) => {
    handlePromises(context);
    context.success = (results) => {
        console.log(results)
        expect(firstPromiseMock).toHaveBeenCalledTimes(1);
        expect(secondPromiseMock).toHaveBeenCalledTimes(1);
        done();
    }
});

或者修改你的代码为 =>

function pushPromises() {
  const promises = [];

  promises.push(firstPromise('something'))
  promises.push(secondPromise('somethingelse'))

  return promises;
}

export default handlePromises = (context) => {
  return Promise.all(pushPromises()).then((data) => context.success(data))
};

//with async
export default handlePromises = async (context) => {
  let data = await Promise.all(pushPromises());
  context.success(data)
};

【讨论】:

  • 为什么我不添加thencatch会起作用?这是如何解决这个问题的?
  • 我已经尝试修改我的代码以不使用上下文,而是返回 Promise.all(pushPromises()) 并且我看到了同样的问题。如果我在第一个承诺中添加then,则不会调用第二个承诺。
  • @HommerSmith returning Promise.all(pushPromises()) 你能告诉我们那个版本吗,因为它应该可以工作。 then / catch 应该对承诺返回没有影响。
  • 它通过让你测试等待所有承诺首先得到解决来解决这个问题,我不太确定如果没有然后阻止@HommerSmith,它是如何工作的
  • 必须是export default handlePromises = () => { return Promise.all(pushPromises()) }); @HommerSmith
【解决方案2】:

在您的编辑中,您的 handlePromises 仍然不是一个承诺..

试试下面的。 ->

it('test', async () => {
  await Promise.all(pushPromises());
  expect(firstPromiseMock).toHaveBeenCalledTimes(1);
  expect(secondPromiseMock).toHaveBeenCalledTimes(1);
});

【讨论】:

  • 为什么我什至需要这样做呢?如果在我的代码中(不是我的编辑)我已经在做const results = await Promise.all(pushPromises()) 不保证所有的承诺都会运行(从测试的角度来看)?
  • @HommerSmith 不,因为您的 handlePromises 不是承诺,所以当您执行 await handlePromises() 时,它不会等待。这解释了为什么您的测试失败了,因为在您的第一个 expect 被调用时,第一个承诺可能已经解决,但是当您的第二个 expect 被调用时,您的第二个承诺可能仍处于未决状态。
  • 我不明白 Keith 为什么会在我介绍 then 并遵守我的承诺时发生这种情况。无论如何,如果我需要那个上下文(编辑将无效,因为我真的需要返回那个 context.success)我会怎么做?
  • @HommerSmith when I introduce then and catch 这只是时间问题。有时 Javascript 引擎可能会优化下一个滴答声,但这是你永远不应该依赖的东西,事实上我很确定在早期的承诺实现中,它保证了下一个滴答声会触发。我不确定上下文是什么以及为什么需要,但您需要做的就是确保 handlePromises() 作为承诺返回,因为目前不是。看看AZ_,他正在用promise.all 返回一个承诺,并支持 then 方法来更新上下文,看起来就像你想要的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 2020-09-12
相关资源
最近更新 更多