简体   繁体   English

如何使用JEST测试Prom递归

[英]How to test promise recursion with JEST

I write a test using JEST. 我用JEST编写了一个测试。 I do not know how to test promise recursion in JEST. 我不知道如何在JEST中测试Promise递归。

In this test, the retry function that performs recursion is the target of the test until the promise is resolved. 在此测试中,执行递归的重试功能是测试的目标,直到承诺被解决为止。

export function retry <T> (fn: () => Promise <T>, limit: number = 5, interval: number = 10): Promise <T> {
  return new Promise ((resolve, reject) => {
    fn ()
      .then (resolve)
      .catch ((error) => {
        setTimeout (async () => {
          // Reject if the upper limit number of retries is exceeded
          if (limit === 1) {
            reject (error);
            return;
          }
          // If it is less than the upper limit number of retries, execute callback processing recursively
          await retry (fn, limit-1, interval);
        }, interval);
      });
  });
}

Perform the following test on the above retry function. 对上述重试功能执行以下测试。

  1. Always pass a promise to resolve, and the retry function is resolved on the first execution 始终传递一个承诺来解决,并且重试函数在第一次执行时就得到解决
  2. Pass the resolve to resolve on the third run, and the retry function is resolved on the third run 在第三次运行时传递resolve进行解析,而retry函数在第三次运行时进行解析

I thought it would be as follows when writing these in JEST. 我认为用JEST编写这些内容时会如下。

describe ('retry', () => {
  test ('resolve on the first call', async () => {
    const fn = jest.fn (). mockResolvedValue ('resolve!');
    await retry (fn);
    expect (fn.mock.calls.length) .toBe (1);
  });

  test ('resolve on the third call', async () => {
    const fn = jest.fn ()
               .mockRejectedValueOnce (new Error ('Async error'))
               .mockRejectedValueOnce (new Error ('Async error'))
               .mockResolvedValue ('OK');
    expect (fn.mock.calls.length) .toBe (3)
  });
});

As a result, it failed in the following error. 结果,它失败并出现以下错误。

Timeout-Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error:
    > 40 | test ('resolve on the third call', async () => {
         | ^
      41 | const fn = jest
      42 | .fn ()
      43 | .mockRejectedValueOnce (new Error ('Async error'))

I think that it will be manageable in the setting of JEST regarding this error. 我认为在有关此错误的JEST设置中将可以管理该错误。 However, fundamentally, I do not know how to test promise recursive processing in JEST. 但是,从根本上讲,我不知道如何在JEST中测试Promise递归处理。

Maybe your retry task take too many times (ex: 4,9s ), then you do not have enough time to do next test case. 也许您的retry任务花费了太多时间(例如: 4,9s ),那么您没有足够的时间来进行下一个测试用例。

You can increase the timeout of JEST with jest.setTimeout(10000); 您可以使用jest.setTimeout(10000);增加JEST的timeout jest.setTimeout(10000);

Promise testing official document. 承诺测试官方文件。

My solution for your case: 我为您解决的方案:

test("resolve on the third call", async () => {
    jest.setTimeout(10000);
    const fn = jest.fn()
      .mockRejectedValueOnce(new Error("Async error"))
      .mockRejectedValueOnce(new Error("Async error"))
      .mockResolvedValue("OK");

    // test reject value
    await expect(fn()).rejects.toEqual(new Error("Async error"));
    await expect(fn()).rejects.toEqual(new Error("Async error"));

    // test resolve
    const result = await fn();
    expect(result).toEqual("OK");

    // call time
    expect(fn).toHaveBeenCalledTimes(3);
  });

The timeout happens because .catch() handler in retry() does not call resolve when it does second attempt to call retry() ; 超时是因为.catch()处理程序中的retry()不调用resolve当它第二次尝试调用retry() ; so the first retry() returns a promise which is never resolved or rejected. 因此,第一个retry()返回一个从未解决或拒绝的承诺。

Replacing await with resolve() might help (and function in setTimeout need not to be async then): resolve()替换await可能会有所帮助(然后setTimeout函数不必异步):

  .catch ((error) => {
    setTimeout (() => {
      // Reject if the upper limit number of retries is exceeded
      if (limit === 1) {
        reject (error);
        return;
      }
      // If it is less than the upper limit number of retries, execute callback processing recursively
      resolve(retry (fn, limit-1, interval));
    }, interval);

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

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