【问题标题】:Testing a function which uses setTimeout with Jest: why is this test failing?测试一个使用 setTimeout 和 Jest 的函数:为什么这个测试失败了?
【发布时间】:2019-03-27 06:41:27
【问题描述】:

我有一个rateLimit 函数(它只是this code 的修改版本):

function rateLimit(func, wait) {
    var timeout;
    return function () {
        var context = this;
        var args = arguments;
        var later = function () {
            timeout = null;
            func.apply(context, args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

这个功能在我的应用程序中运行良好,所以我相当确定实现很好。但是,以下测试失败:

jest.useFakeTimers();

test('rateLimit', () => {
    const action = jest.fn();

    const doAction = rateLimit(action, 100);

    doAction(); // This should increment the call count
    doAction(); // This shouldn't, because 100ms hasn't elapsed yet

    jest.advanceTimersByTime(101);

    doAction(); // This should increment the count again

    expect(action).toHaveBeenCalledTimes(2);
});

出现错误:

Expected mock function to have been called two times, but it was called one time.

Here is a runnable version of this code on repl.it.

我在这里做错了什么?

【问题讨论】:

    标签: javascript unit-testing jestjs


    【解决方案1】:

    您的速率限制器使用trailing 方法,当有新调用时,它会取消当前正在进行的所有调用...直到等待时间到期,此时调用该函数。

    您只需要再次提前计时器,以便再次调用该函数:

    jest.useFakeTimers();
    
    test('rateLimit', () => {
        const action = jest.fn();
    
        const doAction = rateLimit(action, 100);
    
        doAction(); // This should increment the call count
        doAction(); // This shouldn't, because 100ms hasn't elapsed yet
    
        jest.advanceTimersByTime(101);
    
        doAction(); // This should increment the count again
    
        jest.advanceTimersByTime(101);  // <= advance the timers again
    
        expect(action).toHaveBeenCalledTimes(2);  // Success!
    });
    

    【讨论】:

    • 当然...谢谢,我知道我在做傻事!
    【解决方案2】:

    您应该使用第二个调用来触发计时器:

    更多信息here

    test('rateLimit', () => {
      const action = jest.fn();
    
      const doAction = rateLimit(action, 100);
    
      doAction(); // This should increment the call count
      doAction(); // This shouldn't, because 100ms hasn't elapsed yet
    
      jest.runAllTimers();
    
      doAction(); // This should increment the count again
    
      jest.runAllTimers();
    
      expect(action).toHaveBeenCalledTimes(2);
    });
    

    【讨论】:

      猜你喜欢
      • 2021-02-27
      • 2021-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      相关资源
      最近更新 更多