title: How to test that Redux's dispatch() has been called in React Component (Jest + Enzyme)
body: <p>I have a lot of functional React components that call <code>dispatch()</code> (Redux). The <code>dispatch()</code> function itself is passed in by react-redux's <code>useDispatch()</code> hook.</p>
  <p>As a simplified example:</p>
  <pre><code>const LogoutButton: FC = () =&gt; {
    const dispatch: Dispatch = useDispatch();
    
    return (
     &lt;button onClick={() =&gt; {
       console.log(&quot;Clicked...&quot;) // To check that onClick() simulation is working
       dispatch(authActions.logout())  
     }}&gt;
     LOGOUT
     &lt;/button&gt; 
    )
  }
  </code></pre>
  <p>Using Jest and Enzyme, what do I need to do to be able to assert <code>expect(dispatch).toHaveBeenCalledWith(authActions.logout)</code>?</p>
  <p>I don't have a function for mocking the store or use redux-mock-store. Instead, I wrap the components in a Root component I made for testing. It's the same as my real Root component, but takes props for setting up the test's initial store (and history.location):</p>
  <pre><code>const TestRoot: FC&lt;RootProps&gt; = ({ children, initialState = {}, initialEntries = defaultLocation }) =&gt; {
    const store = createStore(reducers, initialState, applyMiddleware(thunk));
  
    return (
      &lt;Provider store={store}&gt;
        &lt;MemoryRouter initialEntries={initialEntries}&gt;
          &lt;ScrollToTop /&gt;
          &lt;StylesProvider jss={jss}&gt;
            &lt;ThemeProvider theme={theme}&gt;{children}&lt;/ThemeProvider&gt;
          &lt;/StylesProvider&gt;
        &lt;/MemoryRouter&gt;
      &lt;/Provider&gt;
    );
  };
  
  </code></pre>
  <p>which is used in tests to set up the Enzyme-wrapped component like:</p>
  <pre><code>wrappedLogoutButton = mount(
    &lt;TestRoot initialState={initialState}&gt;
      &lt;LogoutButton /&gt;
    &lt;/TestRoot&gt;
  );
  </code></pre>
  <p>This set up works nicely for me (so far) and I don't want to change it if I don't have to. I did try injecting a redux-mock-store mock store into TestRoot, but that messed up every single test suite I've written.</p>
  <p>I've tried numerous ways of mocking or spying on both <code>dispatch()</code> and <code>useDispatch()</code> but I haven't been able to see the mock being called. The <code>onClick()</code> simulation is working because I can see &quot;Clicked...&quot; being logged. Here's an example test (real code, not simplified example):</p>
  <pre><code>test('should log learner out', () =&gt; {
      const event = {
        preventDefault: () =&gt; {},
        target: { textContent: en.common['log-out-title'] } as unknown,
      } as React.MouseEvent&lt;HTMLButtonElement, MouseEvent&gt;;
  
      const wrappedLogOut = wrappedMenuDrawer.find(ListItem).at(3).find('a');
  
      // @ts-ignore
      act(() =&gt; wrappedLogOut.prop('onClick')(event));
  
      // TODO: test authService.logout is called
      // assert that dispatch was called with authActions.logout()
      expect(amplitude.logAmpEvent).toHaveBeenCalledWith('from main menu', { to: 'LOGOUT' }); // This assertion passes
    });
  </code></pre>
  <p>Methods/variations I've tried of mocking/spying on dispatch, based on documentation, Medium posts and similar questions on Stack Overflow, include:</p>
  <pre><code>import * as reactRedux from 'react-redux'
  const spy = jest.spyOn(reactRedux, 'useDispatch'
  </code></pre>
  <pre><code>import store from '../../store';
  const spy = jest.spyOn(store, 'dispatch')
  </code></pre>
  <pre><code>const mockUseDispatch = jest.fn();
  const mockDispatch = jest.fn();
  
  jest.mock('react-redux', () =&gt; ({
    useDispatch: () =&gt; mockUseDispatch.mockReturnValue(mockDispatch),
  }));
  
  // or...
  
  jest.mock('react-redux', () =&gt; ({
    useDispatch: () =&gt; mockUseDispatch,
  }));
  
  mockUseDispatch.mockReturnValue(mockDispatch) // inside the actual test
    
  </code></pre>