<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Roland Awoda</title>
    <description>The latest articles on DEV Community by Roland Awoda (@rolandawoda).</description>
    <link>https://dev.to/rolandawoda</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1989335%2Ff267a347-2758-4f74-a817-aeb98c7fc1c1.jpeg</url>
      <title>DEV Community: Roland Awoda</title>
      <link>https://dev.to/rolandawoda</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rolandawoda"/>
    <language>en</language>
    <item>
      <title>Mocking Network Requests Made Easy: Integrating Jest and MSW</title>
      <dc:creator>Roland Awoda</dc:creator>
      <pubDate>Sat, 07 Sep 2024 06:26:13 +0000</pubDate>
      <link>https://dev.to/rolandawoda/mocking-network-requests-made-easy-integrating-jest-and-msw-58ak</link>
      <guid>https://dev.to/rolandawoda/mocking-network-requests-made-easy-integrating-jest-and-msw-58ak</guid>
      <description>&lt;p&gt;Writing unit tests that involve mocking or stubbing API calls can feel overwhelming—I’ve been there myself. In this article, I’ll guide you through a simpler, more efficient way to mock API requests during testing.&lt;br&gt;
Before we dive in, here’s a list of tools we’ll be using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;React Testing Library&lt;/li&gt;
&lt;li&gt;Jest&lt;/li&gt;
&lt;li&gt;Craco : &amp;gt; we will need this to extend jest config later on&lt;/li&gt;
&lt;li&gt;MSW (mock service worker)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don’t worry if you’re not familiar with everything—just follow along, and I’ll walk you through each step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rolandawoda/msw-example" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is the Github link to the project &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;br&gt;
We’ll be building a simple React app that fetches and displays a list of Todos using the &lt;a href="https://jsonplaceholder.typicode.com/" rel="noopener noreferrer"&gt;Json Placeholder API&lt;/a&gt;. In this project, we’ll write test scenarios to verify the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The app shows a loading state while the API request is in progress.&lt;/li&gt;
&lt;li&gt;It displays an error message if the request fails.&lt;/li&gt;
&lt;li&gt;It ensures the list of data from the API is correctly rendered.&lt;/li&gt;
&lt;li&gt;It provides feedback when the request is successful but returns no data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide will cover two main approaches;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Traditional Way of Mocking API Calls&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Modern Approach Using MSW (Mock Service Worker)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;p&gt;To start building the app, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create a new React app:&lt;/strong&gt; Run the following command to create your React application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app msw-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Start the application:&lt;/strong&gt; After the setup, navigate to the project folder and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Install necessary packages:&lt;/strong&gt; Next, install &lt;code&gt;@tanstack/react-query&lt;/code&gt; to manage client-side data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @tanstack/react-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React Query (Tanstack Query) helps in handling server-side state management, including caching, synchronization, and data fetching. You can learn more about it in their &lt;a href="https://tanstack.com/query/latest/docs/framework/react/installation" rel="noopener noreferrer"&gt;Official Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now start writing the app logic and set up React Query to manage data fetching efficiently. Here is what it looks like after setting it up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

import { Todos } from "components/Todos";

const queryClient = new QueryClient();

function App() {
  return (
    &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
      &amp;lt;div data-testid="app" className="App"&amp;gt;
        &amp;lt;Todos /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/QueryClientProvider&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we create the Todos component rendering a list of our todos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Todos.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useQuery } from "@tanstack/react-query";

import { getTodos } from "api/todo";

export function Todos() {
  const { data, isError, isLoading } = useQuery({
    queryFn: getTodos,
    queryKey: ["TODOS"],
  });

  if (isLoading) {
    return &amp;lt;p&amp;gt;loading todo list&amp;lt;/p&amp;gt;;
  }

  if (isError) {
    return &amp;lt;p&amp;gt;an error occurred fetching todo list&amp;lt;/p&amp;gt;;
  }

  return (
    &amp;lt;div&amp;gt;
      {Boolean(data.length) ? (
        &amp;lt;ol&amp;gt;
          {data.map((item) =&amp;gt; (
            &amp;lt;li key={item.id}&amp;gt;{item.title}&amp;lt;/li&amp;gt;
          ))}
        &amp;lt;/ol&amp;gt;
      ) : (
        &amp;lt;p&amp;gt;You do not have todos created yet&amp;lt;/p&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that everything is set up, let’s start writing the tests for the scenarios we outlined earlier. First, we’ll implement this using the traditional approach that we’re already familiar with—mocking API calls using Jest&lt;/p&gt;

&lt;p&gt;Checkout the github &lt;a href="https://github.com/rolandawoda/msw-example" rel="noopener noreferrer"&gt;repo&lt;/a&gt; so you can follow along&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Traditional Way of Mocking API Calls&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React and Jest work seamlessly together out of the box, so there’s no need for additional configuration or setup—at least for now. We’ll create a file named  &lt;code&gt;Todos.test.js&lt;/code&gt; next to our &lt;code&gt;Todo.js&lt;/code&gt; component,  where we’ll import the Todos component and write our tests..&lt;/p&gt;

&lt;p&gt;We have a function called &lt;code&gt;getTodos&lt;/code&gt; which is responsible for making an API call to retrieve the list of todos and returning the response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function getTodos() {
  const response = await fetch("https://jsonplaceholder.typicode.com/todos", {
    headers: {
      "Content-Type": "application/json",
    },
  });

  if (!response.ok) {
    const res = await response.json();
    throw new Error(res.message || response.status);
  }

  return response.json();
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your &lt;code&gt;Todos.test.js&lt;/code&gt; file, you need to import the &lt;code&gt;Todos&lt;/code&gt; component and create a utility function that provides a wrapper with the &lt;code&gt;React Query&lt;/code&gt; provider. This ensures that the &lt;code&gt;Todos&lt;/code&gt; component and its children can use &lt;code&gt;react-query&lt;/code&gt; for managing server state in tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { render, screen, waitFor, within } from "@testing-library/react";

import { Todos } from "./Todos";
import { reactQueryWrapper } from "utils/reactQueryWrapper";
import { getTodos } from "api/todo";

const { wrapper, queryCache } = reactQueryWrapper();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to mock the &lt;code&gt;getTodos&lt;/code&gt; function. This will allow us to specify the return values for each test scenario, giving us control over the data the function returns during testing. Additionally, we’ll ensure that any leftover data from previous test cases is cleaned up, so each test case starts with a clean slate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Code Sample&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jest.mock("api/todo", () =&amp;gt; ({
  getTodos: jest.fn(),
}));

afterEach(() =&amp;gt; {
  queryCache.clear();
  jest.clearAllMocks();
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;Todos.test.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { render, screen, waitFor, within } from "@testing-library/react";

import { Todos } from "./Todos";
import { reactQueryWrapper } from "utils/reactQueryWrapper";
import { getTodos } from "api/todo";

const { wrapper, queryCache } = reactQueryWrapper();

jest.mock("api/todo", () =&amp;gt; ({
  getTodos: jest.fn(),
}));

afterEach(() =&amp;gt; {
  queryCache.clear();
});

afterEach(() =&amp;gt; {
  jest.clearAllMocks();
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;First Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders loading state&lt;/em&gt;&lt;br&gt;
We want to verify that our component correctly displays the loading state while the request is in progress.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders loading state", () =&amp;gt; {
  getTodos.mockImplementation(() =&amp;gt; {
    return new Promise((resolve) =&amp;gt; {
      setTimeout(() =&amp;gt; {
        resolve();
      }, 1000);
    });
  });

  render(&amp;lt;Todos /&amp;gt;, { wrapper });
  const loadingText = screen.getByText("loading todo list");
  expect(loadingText).toBeInTheDocument();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Second Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders error state when request fails or there is network error&lt;/em&gt;&lt;br&gt;
We want to verify that the component correctly renders an error state when the API request fails or encounters a network error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders error state when request fails or there is network error", async () =&amp;gt; {
  getTodos.mockImplementationOnce(() =&amp;gt; {
    return new Promise((resolve, reject) =&amp;gt; {
      reject();
    });
  });

  render(&amp;lt;Todos /&amp;gt;, { wrapper });
  await screen.findByText("an error occurred fetching todo list");
  expect(
    screen.getByText("an error occurred fetching todo list")
  ).toBeInTheDocument();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Third Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders list of todos&lt;/em&gt;&lt;br&gt;
We want to verify that our component correctly renders the list of todos when the request is successful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders list of todos", async () =&amp;gt; {
  getTodos.mockImplementation(() =&amp;gt; {
    return Promise.resolve([
      { id: 1, title: "Exercise" },
      { id: 2, title: "Cook" },
    ]);
  });

  render(&amp;lt;Todos /&amp;gt;, { wrapper });

  const loadingText = screen.queryByText("loading todo list");
  await waitFor(() =&amp;gt; expect(loadingText).not.toBeInTheDocument());
  const list = screen.getByRole("list");
  expect(list).toBeInTheDocument();
  expect(within(list).getAllByRole("listitem")).toHaveLength(2);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fourth Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders list of todos&lt;/em&gt;&lt;br&gt;
We want to verify that your component correctly renders a feedback message when the API request returns an empty list of todos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders feedback message when user has an empty list of todos", async () =&amp;gt; {
  getTodos.mockImplementationOnce(() =&amp;gt; {
    return Promise.resolve([]);
  });

  render(&amp;lt;Todos /&amp;gt;, { wrapper });

  await waitFor(() =&amp;gt;
    expect(screen.queryByText("loading todo list")).not.toBeInTheDocument()
  );
  expect(
    screen.getByText("You do not have todos created yet")
  ).toBeInTheDocument();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Now that we've covered mocking API calls with Jest, let’s explore a better approach using &lt;strong&gt;Mock Service Worker (MSW)&lt;/strong&gt;. &lt;strong&gt;MSW&lt;/strong&gt; provides a more elegant and maintainable way to mock API calls by intercepting network requests at the network level rather than within your tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introducing MSW (Mock Service Worker)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mock Service Worker (MSW) is an API mocking library designed for both browser and Node.js environments. It allows you to intercept outgoing requests, observe them, and provide mocked responses. MSW helps you simulate real-world scenarios in your tests, making them more robust and reliable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mswjs.io/docs/" rel="noopener noreferrer"&gt;Read more about MSW&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up MSW&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Install MSW using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install msw@latest --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Set up the environment you wish to intercept requests in—either Browser or Node. Before doing so, create a mock directory within your src directory. Inside this directory, you'll create the following files and directories:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;browser.js&lt;/code&gt;: Handles request interception in the browser environment.&lt;br&gt;
&lt;code&gt;server.js&lt;/code&gt;: Handles request interception in the Node.js environment.&lt;br&gt;
&lt;code&gt;handlers&lt;/code&gt;: A directory containing files that define the API endpoints to intercept.&lt;/p&gt;

&lt;p&gt;Here’s how your folder structure should look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  └── mock/
      ├── browser.js
      ├── server.js
      └── handlers/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup ensures that you have a clear organization for intercepting and handling requests in both browser and Node.js environments using MSW.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browser Environment Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To set up MSW for intercepting requests in the browser, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create the &lt;code&gt;browser.js&lt;/code&gt; File&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your src/mock directory, create a file named browser.js. This &lt;br&gt;
   file will set up the MSW worker to intercept requests in the &lt;br&gt;
   browser environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// src/mock/browser.js

import { setupWorker } from 'msw/browser';

// Create a worker instance to intercept requests
export const worker = setupWorker();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Generate the &lt;code&gt;mockServiceWorker.js&lt;/code&gt; File&lt;/strong&gt;&lt;br&gt;
   This file is required for MSW to function properly in the browser. &lt;br&gt;
   Generate it using the following command from the root directory of &lt;br&gt;
   your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx msw init &amp;lt;PUBLIC_DIR&amp;gt; --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command initializes the MSW service worker and places the mockServiceWorker.js file into the public directory of your React app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Start the Service Worker&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Import and start the worker in your application entry point &lt;br&gt;
   (typically &lt;code&gt;index.js&lt;/code&gt; or &lt;code&gt;App.js&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// src/index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

if (process.env.NODE_ENV === "development") {
  const mswState = localStorage.getItem("mswState") === "enabled";
  if (mswState) {
    const { worker } = require("./mocks/browser");
    worker.start();
    window.__mswStop = worker.stop;
  }
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;App /&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Verify the Setup&lt;/strong&gt;&lt;br&gt;
   To ensure that the service worker is correctly set up, navigate to &lt;br&gt;
   the URL of your application in the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/mockServiceWorker.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the service worker script displayed in your browser. This confirms that the service worker is correctly installed and ready to intercept requests.&lt;/p&gt;

&lt;p&gt;If your MSW setup is correct and enabled, you should see a console message indicating that MSW is active. Your browser console should display logs similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffke89ccl5015s0zrtl8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffke89ccl5015s0zrtl8y.png" alt="Image description" width="800" height="14"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These logs confirm that the MSW service worker is properly intercepting network requests and is ready to mock API responses according to the handlers you’ve defined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node Environment Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To set up MSW for intercepting requests in a &lt;code&gt;Node.js&lt;/code&gt; environment (for example, in server-side tests), follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create the &lt;code&gt;server.js&lt;/code&gt; File&lt;br&gt;
   In the src/mock directory, create a file named &lt;code&gt;server.js&lt;/code&gt;. This file sets up the MSW server to intercept requests in a &lt;code&gt;Node.js&lt;/code&gt; environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// src/mock/server.js

import { setupServer } from "msw/browser";

// Create a server instance with the defined request handlers
export const server = setupServer();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Define the API Handlers&lt;br&gt;
      Create a file named &lt;code&gt;posts.js&lt;/code&gt; in the &lt;code&gt;handlers&lt;/code&gt; directory.This file will describe the APIs you want to intercept and the mock responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// src/mock/handlers/posts.js

import { http, HttpResponse } from "msw";

export const postHandlers = [

 // Handler for GET /todos request
  http.get("https://jsonplaceholder.typicode.com/todos", () =&amp;gt; {
    return HttpResponse.json([
      { id: 1, title: "totam quia non" },
      { id: 2, title: "sunt cum tempora" },
    ]);
  }),
];

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we're defining that when MSW intercepts a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;https://jsonplaceholder.typicode.com/todos&lt;/code&gt;, it should respond with a &lt;code&gt;200&lt;/code&gt; status code and the provided JSON data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Hook Handlers to the Browser Worker&lt;br&gt;
   Update the &lt;code&gt;browser.js&lt;/code&gt; file to include the defined handlers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { setupWorker } from "msw/browser";

import { postHandlers } from "./handlers/posts";

export const worker = setupWorker(...postHandlers);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Hook Handlers to the Node Server&lt;br&gt;
   Ensure the handlers are also used in the &lt;code&gt;Node.js&lt;/code&gt; environment by updating the &lt;code&gt;server.js&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { setupServer } from "msw/node";

import { postHandlers } from "./handlers/posts";

export const server = setupServer(...postHandlers);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these configurations in place, your MSW setup is complete and ready for both browser and Node.js environments. Congratulations on completing the setup! 🎉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using MSW in our Tests&lt;/strong&gt;&lt;br&gt;
   To use MSW in your tests, you need to set up your test environment to utilize the mock server for intercepting API calls. Here’s a guide to setting up and writing tests using MSW with your Todos component.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create the Test File&lt;/strong&gt;&lt;br&gt;
Create a new file named &lt;code&gt;Todos.MSW.test.js&lt;/code&gt; next to your &lt;br&gt;
&lt;code&gt;Todos.js&lt;/code&gt;component. This file will contain your tests that &lt;br&gt;
utilize MSW for mocking API responses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Up Test Environment&lt;/strong&gt;&lt;br&gt;
In your &lt;code&gt;Todos.MSW.test.js&lt;/code&gt; file, import the necessary modules and &lt;br&gt;
set up the environment for using MSW with your tests. Below is an &lt;br&gt;
example setup:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { render, screen, waitFor, within } from "@testing-library/react";
import { http, delay, HttpResponse } from "msw";

import { Todos } from "./Todos";
import { reactQueryWrapper } from "utils/reactQueryWrapper";
import { server } from "mocks/server";

const { wrapper, queryCache } = reactQueryWrapper();

afterEach(() =&amp;gt; {
  queryCache.clear();
});

afterEach(() =&amp;gt; {
  jest.clearAllMocks();
});

beforeAll(() =&amp;gt; server.listen());
afterEach(() =&amp;gt; server.resetHandlers());
afterAll(() =&amp;gt; server.close());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;First Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders loading state&lt;/em&gt;&lt;br&gt;
We want to verify that our component correctly displays the loading state while the request is in progress.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders loading state", () =&amp;gt; {
  server.use(
    http.get("https://jsonplaceholder.typicode.com/todos", async () =&amp;gt; {
      await delay(1000);
      return HttpResponse.json([]);
    })
  );

  render(&amp;lt;Todos /&amp;gt;, { wrapper });
  const loadingText = screen.getByText("loading todo list");
  expect(loadingText).toBeInTheDocument();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Second Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders error state when request fails or there is network error&lt;/em&gt;&lt;br&gt;
We want to verify that the component correctly renders an error state when the API request fails or encounters a network error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders error state when request fails or there is network error", async () =&amp;gt; {
  server.use(
    http.get("https://jsonplaceholder.typicode.com/todos", async () =&amp;gt; {
      return HttpResponse.json([], {
        status: 500,
      });
    })
  );

  render(&amp;lt;Todos /&amp;gt;, { wrapper });
  await screen.findByText("an error occurred fetching todo list");
  expect(
    screen.getByText("an error occurred fetching todo list")
  ).toBeInTheDocument();
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Third Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders list of todos&lt;/em&gt;&lt;br&gt;
We want to verify that our component correctly renders the list of todos when the request is successful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders list of todos", async () =&amp;gt; {

  render(&amp;lt;Todos /&amp;gt;, { wrapper });

  const loadingText = screen.queryByText("loading todo list");
  await waitFor(() =&amp;gt; expect(loadingText).not.toBeInTheDocument());
  const list = screen.getByRole("list");
  expect(list).toBeInTheDocument();
  expect(within(list).getAllByRole("listitem")).toHaveLength(2);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fourth Test Scenario&lt;/strong&gt;: &lt;em&gt;Renders list of todos&lt;/em&gt;&lt;br&gt;
We want to verify that your component correctly renders a feedback message when the API request returns an empty list of todos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test("Renders feedback message when user has an empty list of todos", async () =&amp;gt; {
   server.use(
    http.get("https://jsonplaceholder.typicode.com/todos", () =&amp;gt; {
      return HttpResponse.json([]);
    })
  );
  render(&amp;lt;Todos /&amp;gt;, { wrapper });

  await waitFor(() =&amp;gt;
    expect(screen.queryByText("loading todo list")).not.toBeInTheDocument()
  );
  expect(
    screen.getByText("You do not have todos created yet")
  ).toBeInTheDocument();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
Mocking API calls is crucial for effective testing, allowing you to simulate different scenarios without relying on real backend services. While traditional Jest mocking can be effective, MSW offers a more sophisticated solution with better support for various environments and more realistic request handling.&lt;/p&gt;

&lt;p&gt;Here are a few tips to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose the Right Tool:&lt;/strong&gt; Use MSW for a more comprehensive &lt;br&gt;
solution that integrates seamlessly with your React application, &lt;br&gt;
especially when dealing with complex request handling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Organize Your Handlers:&lt;/strong&gt; Keep your API handlers well-organized &lt;br&gt;
and modular to make them easier to maintain and extend. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean Up After Tests:&lt;/strong&gt; Ensure that your tests clean up properly &lt;br&gt;
by resetting handlers and clearing mocks to avoid interference &lt;br&gt;
between tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify Setup:&lt;/strong&gt; Always check your setup by inspecting the network &lt;br&gt;
requests and responses to ensure that everything is working as &lt;br&gt;
expected.&lt;br&gt;
By incorporating MSW into your testing strategy, you'll achieve more reliable and maintainable tests, leading to a smoother development experience and higher quality software.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy testing! 🎉&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>unittest</category>
      <category>jest</category>
      <category>msw</category>
    </item>
  </channel>
</rss>
