1

I am new to the redux-toolkit and its testing. I am trying to write a test for a createAsyncThunk that calls an API and updates the state by the data from the API. My async thunk is being called by a button in my component and rather than testing the thunk itself, I am testing its implementation in my component. I am using the Mock Service Worker library to mock my API calls. Following is the screenshot of my failed test
enter image description here

Here is the test that I am running


import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import { rest } from "msw";
import { setupServer } from "msw/node";
import App from "./App";
import { Provider } from "react-redux";
import { createStore } from "./redux/store";

const server = setupServer(
  rest.get("/api", (req, res, ctx) => {
    return res(ctx.json("10"), ctx.delay(150));
  })
);

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

const MockApp: React.FunctionComponent = () => {
  return (
    <Provider store={createStore()}>
      <App />
    </Provider>
  );
};
it("Should simulate the api call", async () => {
  render(<MockApp />);

  const apiButton = screen.getByText("Api call");

  const counter = await screen.findByTestId("displayCount");

  fireEvent.click(apiButton);
  expect(counter).toHaveTextContent("10");
});

My createAsyncThunk is quite simple as well


export const fetchUserById = createAsyncThunk(
  "users/fetchById",
  // Declare the type your function argument here:
  async (userId: number) => {
    const response = await fetch(
      `https://jsonplaceholder.typicode.com/todos/${userId}`
    );
    // Inferred return type: Promise<MyData>
    const res = await response.json();
    return res.userId as MyData["userId"];
  }
);
Ali Raza
  • 73
  • 1
  • 9

1 Answers1

0

You need to deal with the async nature of your thunk by waiting until your exception is true, e.g. like so:

await waitFor(() => expect(counter).toHaveTextContent("10"))

That way the test waits for

  • the thunk to do the http call and notify the component consuming it with the result data
  • the component to re-render
  • the assertion to be true

See the RTL docs.

geoM
  • 447
  • 4
  • 12
  • true. But I have added the wait for the **textContent** to appear but it's not working. I think it has something to do with the mock server. – Ali Raza Feb 15 '22 at 19:55
  • Is that line executed during the test? `return res(ctx.json("10"), ctx.delay(150))`? Can you verify that e.g. using a console log? – geoM Feb 16 '22 at 22:08
  • As per MSW docs, we need to give the absolute url of the endpoint. You have given just '/api'. Could you make it absolute path starting from http:// or https://? – CodeBuggy Feb 17 '22 at 19:01