Testing debounced function in React component with Jest and Enzyme

后端 未结 1 757
慢半拍i
慢半拍i 2021-01-19 04:59

I am testing a React component using Jest and Enzyme, and am having difficulty testing that a debounced function is called properly (or at all). I\'ve simplified the compone

相关标签:
1条回答
  • 2021-01-19 05:17

    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 setTimeout will lead to infinite recursion error, since mocked setTimeout() 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) while debounce uses both setTimeout and Date 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()
    
    await act(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")
    
    await act(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()
    
    await act(async () => {
      triggerDebounced()
      jest.advanceTimersByTime(DEBOUNCED_TIME)
    })
    
    0 讨论(0)
提交回复
热议问题