Jasmine:如何测试异步函数?

Jasmine: how to test async function?

在我的 NodeJS 应用程序中,我通过一种方法获得了以下 heplers.ts 文件,wait:

export const wait = async (ms: number) => {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
};

我目前正在为此文件编写单元测试,这就是我现在拥有的:

import { setProcessEnv } from 'spec/helpers';
import { wait } from '../../util/helpers';

describe('Helper methods', () => {
  beforeEach(() => {
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
    setProcessEnv();
  });

  it('should wait a specified amount of time', async () => {
    const TIMEOUT = 10000;
    jasmine.clock().install();  // First install the clock

    await wait(TIMEOUT);

    jasmine.clock().tick(10000); // waits till 10000 milliseconds

    expect(wait).toHaveBeenCalled();
    
    jasmine.clock().uninstall(); // uninstall clock when done
  });
  
});

但我不断收到

Error: Timeout - Async function did not complete within 20000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)

我已经将 jasmine.DEFAULT_TIMEOUT_INTERVAL 增加到 20000 毫秒,但它仍然不起作用。 如何测试此类异步函数?

我找到了双门轿跑车示例,但它们在我的案例中不起作用:How to test a function which has a setTimeout with jasmine?

更新

这是我的最新版本,不会抛出错误,但问题是它没有涵盖 return 语句行 (return new Promise(...):

it('should wait a specified amount of time', async () => {
     const TIMEOUT = 10000;

    // jasmine.clock().install();  // First install the clock
    const wait = jasmine.createSpy();

    await wait(TIMEOUT);

    // jasmine.clock().tick(1000); // waits till 10000 milliseconds
    expect(wait).toHaveBeenCalled();
    expect(wait).toHaveBeenCalledWith(TIMEOUT);
    
    // jasmine.clock().uninstall(); // uninstall clock when done
  });

问题在于,使用jasmine 的自定义时钟,您需要手动调用.tick() 来将时间向前移动。由于您立即等待 wait 调用,因此 wait 内的 setTimeout 将无法到达。因此,当您在等待承诺后调用 .tick() 时,承诺永远不会解决。

您可以通过不立即等待从 wait 返回的承诺来解决此问题,而是将其分配给变量然后提前时间。然后,等待承诺并检查 wait 是否已被调用:

describe('Helper methods', () => {

    it('should wait a specified amount of time', async () => {
        const TIMEOUT = 10000;
        jasmine.clock().install();  // First install the clock

        const waitPromise =  wait(TIMEOUT);
        jasmine.clock().tick(10000); // waits till 10000 milliseconds

        await waitPromise; // now await the promise

        expect(wait).toHaveBeenCalled();

        jasmine.clock().uninstall(); // uninstall clock when done
    });
});

请注意,在上面的代码中没有在 wait 上设置间谍,因此 .toHaveBeenCalled 可能会失败。如果您需要帮助设置一个函数的间谍,请检查此 link:


回答更新后的问题:您错误地设置了间谍。您需要将其更改为:

import { setProcessEnv } from 'spec/helpers';
import * as WaitFunction from from '../../util/helpers';
...
it('should wait a specified amount of time', async () => {
    const TIMEOUT = 10000;    
    
    const waitSpy = spyOn(WaitFunction, 'wait').and.callThrough();

    await WaitFunction.wait(TIMEOUT);

    expect(waitSpy).toHaveBeenCalled();
    expect(waitSpy).toHaveBeenCalledWith(TIMEOUT);
    
  });