最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to mock useLocation correctly? - Stack Overflow

programmeradmin3浏览0评论

I have a component that uses useLocation hook to get the path from the URL.

const { pathname } = useLocation();
useEffect(() => { }, [pathname]);

While I am trying to mock the location using ,

import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '@testing-library/react';
import { shallow } from 'enzyme';

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useLocation: () => ({
    pathname: 'https://URL/'
  })
}));

describe('<ExampleComponent />', () => {
  it('should render correctly', () => {
    shallow(<ExampleComponent />);
  });
});

I am getting this error while I run the test, TypeError: Cannot read property 'location' of undefined

I have a component that uses useLocation hook to get the path from the URL.

const { pathname } = useLocation();
useEffect(() => { }, [pathname]);

While I am trying to mock the location using ,

import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '@testing-library/react';
import { shallow } from 'enzyme';

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useLocation: () => ({
    pathname: 'https://URL/'
  })
}));

describe('<ExampleComponent />', () => {
  it('should render correctly', () => {
    shallow(<ExampleComponent />);
  });
});

I am getting this error while I run the test, TypeError: Cannot read property 'location' of undefined

Share Improve this question edited Jun 14, 2021 at 5:22 Vegeta asked Jun 14, 2021 at 5:01 VegetaVegeta 1191 gold badge2 silver badges9 bronze badges 2
  • I would suggest you don't mock it, mount the component in e.g. a MemoryRouter or create a history for testing purposes; see stackoverflow.com/a/65275037/3001761, reactrouter.com/web/guides/testing – jonrsharpe Commented Jun 14, 2021 at 8:34
  • the correct way is to use MemoryRouter as below in the answer stackoverflow.com/a/74820547/6127865 – Abasaheb Gaware Commented Dec 16, 2022 at 5:43
Add a comment  | 

6 Answers 6

Reset to default 6

Below is how I have done this in my tests. * Note I am using typescript

import routeData from 'react-router';    

    describe('Login Page UnitTests', () => {
      const useLocation = jest.spyOn(routeData, 'useLocation');
    
      beforeEach(() => {
        useLocation.mockReturnValue({ search: 'testQueryParameters'} as any);
      });

      // Add unit tests
    }

Ensure that you clear the mock to avoid issue with data in subsequent tests

Try mocking the useLocation as jest.fn().mockImplementation

jest.mock('react-router', () => ({
...jest.requireActual("react-router") as {},
   useLocation: jest.fn().mockImplementation(() => {
    return { pathname: "/testroute" };
   })
}));

The correct way to mock useLocation is below:

import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '@testing-library/react';
import { MemoryRouter} from 'react-router-dom';
import { shallow } from 'enzyme';

const renderComponent = () => {
  return (
      <MemoryRouter
          initialEntries={["/one", "/two", { pathname: 'https://URL/' }]}
          initialIndex={1}>
         <ExampleComponent />
     </MemoryRouter>
   );
}

describe('<ExampleComponent />', () => {
  it('should render correctly', () => {
    shallow(renderComponent());
  });
});

Finally found the simplest way to mock useLocation:

import { useLocation } from 'react-router-dom';

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useLocation: jest.fn()
}));

const mockUseLocation = useLocation as jest.MockedFunction<typeof useLocation>;

Now you can mock the return value inside any test case. For example:

it('should render', () => {
    mockUseLocation.mockReturnValue({
      search: '?param=1'
    });

    // ...
});

If you're using typescript, you can set a const to define the default values of all the properties:

const defaultUseLocationResult = { pathname: '', search: '', state: {}, hash: '' };

and apply it as follows:

mockUseLocation.mockReturnValue({
    ...defaultUseLocationResult,
    search: '?param=1'
});

This works for me

import * as router from 'react-router';

    jest
      .spyOn(router, 'useLocation')
      .mockReturnValue({ pathname: '/department/details/1213', search: '', state: {}, hash: '' });

I'll post something additional here where you want mock useLocation with state variables.

Code

Here I'm navigating from page1 to page2 and I want to pass a state variable to new route.

navigate('/another/page2', {state: {name: 'john'}});

Then inside page to I can read the location state.

const location = useLocation();
const locationState = location.state as { name?: string };

Test

I can mock useLocation with location state as below.

const mockUseLocation = {
    pathname: '/another/page2',
    key: '',
    search: '',
    hash: '',
    state: { name: 'mock name' },
};

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useLocation: () => mockUseLocation,
}));

it('test1', async () => {
    // write your test here
});
发布评论

评论列表(0)

  1. 暂无评论