skip to Main Content
...

const MovieDetails = () => {
  ...

  let { movieId } = useParams();
  const [movie, setMovie] = useState(null);
  
  useEffect(() => {
    // axios settings
    let unmounted = false;
    let source = axios.CancelToken.source();
    axios.get(`http://localhost:4000/movies/${movieId}`, {
      cancelToken: source.token
    }).then(result => {
      if (!unmounted) {
        setMovie(result.data)
      }
    }).catch(function (e) {
      if (!unmounted) {
        if (axios.isCancel(e)) {
          console.log(`request cancelled:${e.message}`);
        } else {
          console.log("another error happened:" + e.message);
        }
      }
    });
    return function () {
      unmounted = true;
      source.cancel("Cancelling in cleanup");
    };
  }, [movieId]);

  return (
    <div className={styles.movieDetail}>
      {movie && (
...

export default MovieDetails;

How can I write a unit test for this code above?

It includes axios, useEffect and useParams.

Basically, I am listing movies and it is showing movie details on click.

My test is looking like this for now:

It is failing on render part because somehow I have to use useParams with axios

...

describe('MovieDetails', () => {
  let testList = movieList;

  test('render movie details when a movie is selected', () => {
    render(
      <MemoryRouter>
        <MovieDetails />
      </MemoryRouter>
    );
    const element = screen.getByTestId('movieDetails');
    expect(element).toBeInTheDocument();
    const image = element.querySelector("img");
...

export default MovieDetails;

2

Answers


  1. You can use jest to mock axios, and MemoryRouter to simulate a URL for movieId. Let me know if something like this helps:

    import React from 'react';
    import { render, screen } from '@testing-library/react';
    import MovieDetails from './MovieDetails';
    import { MemoryRouter } from 'react-router-dom';
    import axios from 'axios';
    
    jest.mock('axios');
    
    describe('MovieDetails', () => {
      const movieId = 1;
      const mockMovieData = {
        // Put your data here
      };
    
      beforeEach(() => {
        axios.get.mockResolvedValue({ data: mockMovieData });
      });
    
      test('renders stuff when a movie is selected', async () => {
        render(
          <MemoryRouter initialEntries={['/movies/1']}>
            <MovieDetails />
          </MemoryRouter>
        );
    
        await waitFor(() => {
          expect(screen.getByTestId('movieDetails')).toBeInTheDocument();
          // Place your assertions here for the rendered elements
        });
      });
    });
    
    Login or Signup to reply.
  2. You are on the right track using the MemoryRouter, but you’ll also need to render MovieDetails on a route with a path that has a movieId parameter.

    Example:

    import {
      MemoryRouter,
      Routes,
      Route,
    } from 'react-router-dom';
    
    test('render movie details when a movie is selected', () => {
      render(
        <MemoryRouter initialEntries={["/movies/1234"]}>
          <Routes>
            <Route
              path="/movies/:movieId"
              element={<MovieDetails />}
            />
          </Routes>
        </MemoryRouter>
      );
    
      ...
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search