Testing Debounced Function In React Component With Jest And Enzyme
Solution 1:
NOTE: this answer also applies to lodash.throttle
since it is just a wrapper of debounce
.
Lodash's debounce
is a monster and needs some special treatments in test because not only does it use setTimeout()
but it also:
Calls
setTimeout()
recursively: This means callingjest.runAllTimers()
to mocksetTimeout
will lead to infinite recursion error, since mockedsetTimeout()
executes synchronously until it runs out of task, which is not the case here.Uses
Date
API: Jest v25 and below only mocks timer functions (e.g.setTimeout
,setInterval
) whiledebounce
uses bothsetTimeout
andDate
so we need to mock both of them.
How you fix this problem depend on what version of jest you are using.
For jest version 25 and below:
Use another library to mock Date
object. In this example I'll use advanceBy()
from jest-date-mock
jest.useFakeTimers()
awaitact(async () => {
triggerDebounced()
advanceBy(DEBOUNCED_TIME + 1000) // forward Date
jest.advanceTimersByTime(DEBOUNCED_TIME) // forward setTimeout's timer
})
Jest version 26:
Jest version 26 introduces modern mode for fake timers which mocks both Date
and timer functions, it's an opt-in feature, so in order to use it you need to add jest.useFakeTimers('modern')
before the test runs
jest.useFakeTimers("modern")
awaitact(async () => {
triggerDebounced()
jest.advanceTimersByTime(DEBOUNCED_TIME)
})
Jest version 27+:
According to this PR, Jest v27 will use the modern implementation by default so we don't need to specify it explicitly.
jest.useFakeTimers()
awaitact(async () => {
triggerDebounced()
jest.advanceTimersByTime(DEBOUNCED_TIME)
})
Post a Comment for "Testing Debounced Function In React Component With Jest And Enzyme"