React - Testing Network Requests in 3 Simple Steps
Published: 2021-09-11 19:47:12

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnc99tfdai9710p74lr0.png)

The component that we will be testing will be simple. The component will fetch the [randomuser](https://randomuser.me/) 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` and`msw`(Mock Service Worker) as a dependency. Lastly, we'll build our component in `App.js`.
```javascript
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>
  );
}
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kx5tf6jbcbk8rknsbezp.png)
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](https://mswjs.io/docs/getting-started/mocks/rest-api)
 

Now go into your `handlers.js` file and paste the code below.
``` javascript
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"
            }
          }
        ],
      })
    );
  }),
];
```
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.

``` javascript
// 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);
```
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](https://mswjs.io/docs/getting-started/integrate/node).

```javascript
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())
```

## 3. write test
Finally, we write the test in `App.test.js`.
```javascript
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();
});
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jxhjtbrp4nw4m3su5x32.png)