繁体   English   中英

如何使用 Jest 测试在 catch 语句中重新抛出错误

[英]How to test that an error is re-thrown in a catch statement with Jest

我有一个返回 promise 的 function,但我想测试它是否定义了一个 catch,然后另外测试它是否重新抛出错误。

这是一个非常人为的例子,但它是展示问题的最清晰的方式。 在我的实际代码中,我正在调用模拟失败的 function(与此示例中的手动拒绝相比),并且我在catch语句中有额外的日志记录,这解释了错误的重新抛出。

const foo = () => {
  return new Promise((resolve, reject) => {
    reject(new Error('reject')); // manually rejecting to mimic actual code...
  }).catch(error => {
    // do some additional logging...
    throw error;
  });
};

it('should catch and re-throw error', () => {
  // Received function did not throw
  // and
  // Unhandled promise rejection
  expect(() => foo()).toThrow();

  // Test passes, even when `throw error` is commented out with false positive
  expect(foo()).rejects.toThrow();
});

我可以成功检查日志记录 function 是否被调用,但无法弄清楚如何确保错误在之后重新抛出。

工作更新:)

感谢@skyboyer@Bergi让我以不同的方式思考这个问题,并让我接触到一些有趣的笑话

下面是显示日志记录 function 的更新代码,以及我确定的更新测试。

导致这种情况的问题是

  • 由于重新抛出错误,无法测试logging被调用
  • 无法测试重新抛出的错误的值

抓住被拒绝的 promise 让我可以做到这两点。

我本来打算在rejects.toEqual测试中离开,但现在看来是多余的......

对任何反馈感兴趣! 再次感谢!

// myModule.js
export const logging = () => {};
export const bar = () => new Promise(resolve => {});
export const foo = () => {
  return bar().catch(error => {
    logging();
    throw error;
  });
};

describe('myModule', () => {
  let fooReturn;

  beforeEach(() => {
    jest.clearAllMocks();

    jest.spyOn(myModule, 'bar').mockImplementation(() => {
      return Promise.reject({ error: 'bar error' });
    });

    jest.spyOn(myModule, 'logging').mockImplementation(() => {});

    fooReturn = myModule.foo();
  });

  it('should catch and re-throw error', () => {
    expect.assertions(1);
    fooReturn.catch(result => expect(result).toEqual({ error: 'bar error' }));

    // removed since the above test covers that the promise was rejected
    // return fooReturn.rejects.toEqual(expect.anything());
  });

  it('should call the loggin method', async () => {
    expect.assertions(1);

    // prevents UnhandledPromiseRejectionWarning
    fooReturn.catch(() => {});

    expect(myModule.logging).toBeCalled();
  });
});

你错过了return

https://jestjs.io/docs/asynchronous#resolves——拒绝

请务必返回断言——如果您省略此返回语句,您的测试将在解析从 fetchData 返回的 promise 之前完成,然后 then() 有机会执行回调。

你的测试应该是

it('should catch and re-throw error', () => {
  return expect(foo()).rejects.toEqual(expect.anything());
});

正如你/Bergi 注意到的那样, async/await看起来更简洁:

it('should catch and re-throw error', async () => {
  await expect(foo()).rejects.toEqual(expect.anything());
});

但是如果我们错过了在expect之前添加await ,我们将遇到与没有return的版本 1 中完全相同的问题。 所以要小心。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM