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 calling- jest.runAllTimers()to mock- setTimeoutwill lead to infinite recursion error, since mocked- setTimeout()executes synchronously until it runs out of task, which is not the case here.
- Uses - DateAPI: Jest v25 and below only mocks timer functions (e.g.- setTimeout,- setInterval) while- debounceuses both- setTimeoutand- Dateso 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"