Pesquisa de site

reactjs - Como simular corretamente o hook useParams no jest


Estou tentando simular o hook useParams no Jest e tentar torná-lo dinâmico para poder simulá-lo algumas vezes. No entanto, só consigo simulá-lo se eu codificar o valor manualmente. Aqui está o que consegui até agora:

const mockedUsedNavigate = jest.fn();

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
  useNavigate: () => mockedUsedNavigate,
  useParams: () => ({
    hash: '123',
  }),
}));

Isso funciona porque estou codificando diretamente o useParam para retornar um objeto { hash: '123' }. No entanto, se eu tentar simular isso, não vai funcionar:

const mockedUsedNavigate = jest.fn();

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
  useNavigate: () => mockedUsedNavigate,
  useParams: () => jest.fn().mockReturnValue({ hash: '123' })
}));

Se eu fizer isso, meu componente receberá um valor vazio e o valor não será simulado da maneira que eu quero:

  const { hash = '' } = useParams<{ hash: string }>();
  console.log('hash: ', hash); ---> ''

Então, não tenho certeza do que estou fazendo de errado... Alguém pode me indicar a direção certa?

Resposta #1

O useParams geralmente retorna os parâmetros da rota com base na rota atual. Portanto, não é uma função que pode ser simulada usando jest.fn(). O hook useParams retorna um objeto de pares chave/valor dos parâmetros dinâmicos da URL atual que foram correspondidos pelo <Route path>. Veja aqui ---> documentação do React Router

Quando você usa jest.fn().mockReturnValue({ hash: '123' }), ele retorna uma função, não um objeto. Portanto, chamar useParams<{ hash: string }>() resultará em um objeto vazio ({}).

Para simular useParams com um valor específico, você pode retornar diretamente o objeto com as propriedades desejadas. Modifique seu código abaixo:

    
const mockedUseNavigate = jest.fn();

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
  useNavigate: () => mockedUseNavigate,
  useParams: () => ({ hash: '123' }),
}));

Dessa forma, quando seu componente chamar useParams<{ hash: string }>(), ele receberá o objeto { hash: '123' }. Não há necessidade do jest.fn() adicional e do mockReturnValue.

Para simular o useParams com valores dinâmicos no Jest, você pode usar uma das seguintes maneiras:

import { render, screen } from '@testing-library/react';
import { BrowserRouter, MemoryRouter, Route, useParams } from 'react-router-dom';

// Mock the useParams hook
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useParams: jest.fn(),
}));

describe('YourComponent', () => {
  test('renders with dynamic useParams', () => {
    // Set the desired dynamic value for testing
    useParams.mockReturnValue({ hash: '123' });

    render(
      <MemoryRouter initialEntries={['/your-route/123']}>
        <YourComponent />
      </MemoryRouter>
    );

    // Your testing logic here

    // Ensure that the component received the dynamic value
    const hashValue = screen.getByText(/hash/i).textContent;
    expect(hashValue).toBe('123');
  });
});

OU

import { render } from '@testing-library/react';
import { BrowserRouter as Router } from 'react-router-dom';
import YourComponent from './YourComponent'; // Import your component

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

describe('YourComponent', () => {
  test('should render with dynamic useParams', () => {
    // Mock the dynamic useParams value
    jest.spyOn(require('react-router-dom'), 'useParams').mockReturnValue({ hash: '123' });

    // Render your component within a Router
    render(
      <Router>
        <YourComponent />
      </Router>
    );
  });
});

Aqui useParams é declarado fora do describe() e seu valor é alterado em cada teste unitário usando jest.spyOn.

OU

let dynamicHash = '123'; // Set your initial value

const mockedUseNavigate = jest.fn();

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: () => mockedUseNavigate,
  useParams: () => ({ hash: dynamicHash }),
}));

Artigos relacionados