Search code examples
reactjsjestjsmockingreact-hooksreact-router-dom

react jest mock useNavigate()


"react-router-dom": "^6.0.0-alpha.5",

I have tried nearly everything.

I just want to mock this navigate() call from the useNavigate() hook. that's it. Simple. Nothing working.

No, i do not want to use Link. useNavigate is used programmatically in other places as well and I want to mock them too

import React from 'react'
import { useNavigate } from "react-router-dom"

export const Detail = () => {
    const navigate = useNavigate();
    return (
        <span onClick={() => navigate('/some/specific/route')}>
            some Text
        </span>
    )
}

I have tried these:

jest.mock('react-router-dom', () => {
    // Require the original module to not be mocked...
    const originalModule = jest.requireActual('react-router-dom');

    return {
        __esModule: true,
        ...originalModule,
        // add your noops here
        useNavigate: jest.fn(() => 'bar')
    };
});
import * as ReactRouterDom from "react-router-dom";
...
// cannot redefine property
          Object.defineProperty(ReactRouterDom, 'useNavigate', {
              configurable: true,
              value: jest.fn(() => 'bar')
          });
// doesnt work
          jest.mock('react-router-dom', () => ({
              useNavigate: jest.fn(() => jest.fn),
          }))
// doesnt work
jest.spyOn(ReactRouterDom, 'useNavigate', 'get').mockReturnValue(jest.fn(() => jest.fn));
// doesnt work
jest.spyOn(ReactRouterDom, 'useNavigate').mockReturnValue(jest.fn(() => jest.fn));
// doesnt work
const mockedUsedNavigate = jest.fn();

jest.mock('react-router-dom', () => ({
   ...jest.requireActual('react-router-dom') as any,
  useNavigate: () => mockedUsedNavigate,
}));

all of these either show "Cannot redefine Property 'useNavigate'", or that useNavigate() may be used only in the context of a <Router> component.

Seriously, any other import mock works fine.

What am I doing wrong?

MY MINIMUM RECREATED PROJECT: https://github.com/zacharytyhacz/useNavigateBug


Solution

  • I had a similar concern that was fixed with this issue from react router

    I would suggest you change the mock as is:

    // pay attention to write it at the top level of your file
    const mockedUsedNavigate = jest.fn();
    
    jest.mock('react-router-dom', () => ({
       ...jest.requireActual('react-router-dom') as any,
      useNavigate: () => mockedUsedNavigate,
    }));
    
    
    // your describe/it/test blocks go down there