DEV Community

Chris
Chris

Posted on • Edited on

React - Testing Network Requests in 3 Simple Steps

Want to test your React app when making a fetch request? This article will go over how to integrate msw(Mock Service Worker) to intercept a specific network request made on your app. To test and make sure our app behaves as intended.

1. Creating our Component

Screen Shot 2021-09-11 at 12.27.54 PM

The component that we will be testing will be simple. The component will fetch the randomuser API to retrieve a random first and last name. And then display a text on the screen The name is {firstname} {lastname}.

First, create a React App using npx create-react-app. Then run npm install axios msw in the terminal to install axios andmsw(Mock Service Worker) as a dependency. Lastly, we'll build our component in App.js.

import { useState, useEffect } from "react";
import axios from "axios";
const url = 'https://randomuser.me/api/?inc=name'

export default function App() {
  const [fullName, setFullName] = useState('')
  useEffect(() => {
    axios.get(url)
    .then(({data}) => {
      const {first, last} = data.results[0].name
      setFullName(`${first} ${last}`)
    })
  }, [])

  return (
    <div className="App">
      <p>The name is {fullName}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

We use useEffect to make our fetch request when the component mounts. Then we extract the first and last and update our fullName state. And at the end, we return our JSX to print out the text, including the full name from our state. If you run npm start everything should display correctly.'

2. MSW(Mock Service Worker) Setup

Screen Shot 2021-09-11 at 12.54.45 PM
To set up our msw, we first create a new mocks folder in our src directory. Then create two files in our mock directory. The first file will be named server.js, and the second will be handlers.js.documentation reference

Now go into your handlers.js file and paste the code below.

import { rest } from 'msw';

export const handlers = [
  rest.get('https://randomuser.me/api', (req, res, ctx) => {
    return res(
      ctx.json({
        results: [
          {
            name: {
              title: "Mrs",
              first: "Chris",
              last: "Lemus"
            }
          }
        ],
      })
    );
  }),
];
Enter fullscreen mode Exit fullscreen mode

Here we add the response data to any network request whenever we run our test. And the handlers array to store all of our mock server responses. For this demo, we only need to add a mock server response for a GET request made to https://randomuser.me/api/?inc=name.
The response will return an object containing data for the first name and last name, in the same format our randomuser API would respond.

Next, paste the code below into server.js to set up the server.

// src/mocks/server.js
import { setupServer } from 'msw/node';
import { handlers } from './handlers';

// This configures a request mocking server with the given request handlers.
export const server = setupServer(...handlers);
Enter fullscreen mode Exit fullscreen mode

The last step to setting up our msw is to update our React test configuration; this will intercept all network requests specified in our handlers. So paste the code below into setupTests.js in the src directory. Reference to the code provided can be found on the msw documentation.

import { server } from './mocks/server.js'
// Establish API mocking before all tests.
beforeAll(() => server.listen())
// Reset any request handlers that we may add during the tests,
// so they don't affect other tests.
afterEach(() => server.resetHandlers())
// Clean up after the tests are finished.
afterAll(() => server.close())
Enter fullscreen mode Exit fullscreen mode

3. write test

Finally, we write the test in App.test.js.

import { render, screen } from '@testing-library/react';
import App from './App';

test('displays name from api correctly', async() => {
  render(<App />);
  const text = await screen.findByText(/chris lemus/ig);
  expect(text).toBeInTheDocument();
});
Enter fullscreen mode Exit fullscreen mode

The test ensures that the name is printed correctly after making the network request. Since we will be making a network request in our App.js component, we will provide an asynchronous callback function for our test.

The last step will be to run npm test, where our test should run successfully.
Screen Shot 2021-09-11 at 1.40.45 PM

Top comments (2)

Collapse
 
kettanaito profile image
Artem Zakharchenko

A great overview, Chris!

One thing I'd point out, is that you don't have to specify query parameters when declaring the request URL in your handler:

-https://randomuser.me/api/?inc=name
+https://randomuser.me/api/
Enter fullscreen mode Exit fullscreen mode

Query parameters don't describe the path to the requested resource and should be dropped. The values of those parameters can still be accessed under req.url.searchParams in your resolver if you need them.

Collapse
 
chrislemus profile image
Chris

I've updated the request URL in my handler. Thanks for the feedback!