DEV Community

Lumin
Lumin

Posted on

5 1

Test `history` in React Router

Problem

When we use hooks useHistory of react-router-dom
How to expect the history are changes?
How to mock the history?

Solution

Don't try to expect global window.location or window.history.
Just render test component as a children of <Router>, it's require history object just create a simple Javascript object with mock on specific function (depend on your needs)

example from React Router document :p

// HomeButton.jsx
import { useHistory } from "react-router-dom";

export function HomeButton() {
  let history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button data-testid="button" type="button" onClick={handleClick}>
      Go home
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

the test file

// HomeButton.test.jsx
import { render, screen, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { HomeButton } from './HomeButton';

describe('HomeButton', () => {
  // the test might throw an error about required properties, it's depend on your component's dependencies.
  const mockHistory = {
    push: jest.fn(),
  }

  it('should go to home after click', () => {
    await act(async () => {
      render(
        <Router history={mockHistory}>
          <HomeButton />
        </Router>
      )

      userEvent.click(screen.getByTestId('button'))
    })

    expect(mockHistory.push).toBeCalledTime(1)
    expect(mockHistory.push).toBeCalledWith("/home")
  })
})
Enter fullscreen mode Exit fullscreen mode

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (2)

Collapse
 
macnick profile image
Nick Haralampopoulos

Mocking is a code smell. I will explain why.
If, for some reason, history changes the method name from push to gotoPath the test will pass because the function is mocked but the code will be broken.
Also the test does not test if it actually goes to the url /home, actually it tests if the mocked function is called with /home

Collapse
 
edfildesho profile image
edfildesHO • Edited

How do you write unit tests without mocking ever? Surely if you have to include every dependency all the time you're going to end up writing integration tests no?

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more