Search code examples
reactjsaxiosreact-hooksreact-testing-librarymsw

Unable use mock servise worker in react testing library


Instead of mocking an axios request, I try to test the component using msw, but after the request I don't get the visibility of the content in the component, what am I doing wrong?

My component

import React, {useEffect, useState} from 'react'
import axios from "axios";


export default function TestPage() {

  const [testData, setTestData] = useState('')

  useEffect(() => {
    const getSomeData = async () => {
      const data = await axios.get('https://jsonplaceholder.typicode.com/todos/1')
      setTestData(data.data.title)
    }
    getSomeData()
  }, [])

  return (
      <div className='test'>
        <h1>{testData}</h1>
      </div>
  )
}

My test file

import React from 'react'
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import {render, act, screen} from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import TestPage from "../testPage";


const allUsers = [
  {title:'User'}
]

const server = setupServer(
    rest.get('https://jsonplaceholder.typicode.com/todos/1', async (req, res, ctx) => {
      return res(ctx.json( {data: allUsers} ));
    })
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers())
afterAll(() => server.close());

test('loads and displays greeting', async () => {
  await act(async () => {
    await render(<TestPage/>)
  })
  await screen.findByText('User') //I have no response content here
  screen.debug()
})

Solution

  • You do not need to define the data field for ctx.json(), the resolved value of the axios.get() method has a data field. See Response schema

    In addition, the data returned by the API is an array.

    You don't need to use the act helper function, wait for the result of the API call operation in your test by using one of the async utilities like waitFor or a find* query is enough.

    E.g.

    TestPage.tsx:

    import React, { useEffect, useState } from 'react';
    import axios from 'axios';
    
    export default function TestPage() {
      const [testData, setTestData] = useState('');
    
      useEffect(() => {
        const getSomeData = async () => {
          const res = await axios.get('https://jsonplaceholder.typicode.com/todos/1');
          console.log(res.data);
          setTestData(res.data[0]?.title);
        };
        getSomeData();
      }, []);
    
      return (
        <div className="test">
          <h1>{testData}</h1>
        </div>
      );
    }
    

    TestPage.test.tsx:

    import React from 'react';
    import { rest } from 'msw';
    import { setupServer } from 'msw/node';
    import { render, screen } from '@testing-library/react';
    import '@testing-library/jest-dom/extend-expect';
    import TestPage from './TestPage';
    
    const allUsers = [{ title: 'User' }];
    
    const server = setupServer(
      rest.get('https://jsonplaceholder.typicode.com/todos/1', async (req, res, ctx) => {
        return res(ctx.json(allUsers));
      })
    );
    
    beforeAll(() => server.listen());
    afterEach(() => server.resetHandlers());
    afterAll(() => server.close());
    
    describe('67902700', () => {
      test('loads and displays greeting', async () => {
        render(<TestPage />);
        await screen.findByText('User');
        screen.debug();
      });
    });
    

    test result:

     PASS  examples/67902700/TestPage.test.tsx (7.499 s)
      67902700
        ✓ loads and displays greeting (65 ms)
    
      console.log
        [ { title: 'User' } ]
    
          at examples/67902700/TestPage.tsx:10:15
    
      console.log
        <body>
          <div>
            <div
              class="test"
            >
              <h1>
                User
              </h1>
            </div>
          </div>
        </body>
    
          at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:82:13)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        7.978 s