我有一个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。
我在这里做什么错了?
答案 0 :(得分:3)
您的速率限制器使用一种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!
});
答案 1 :(得分:0)
您应该使用第二个调用来启动计时器:
更多信息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);
});