简体   繁体   中英

How to write a React Component unit test with useEffect hook and async call?

I'm starting with a basic create-react-app app and trying to learn the proper unit testing techniques. I updated the initial App component to call a local node API for a basic string response. I can't seem to find in the documentation on how to test that the paragraph tag get's the mocked response in my test.

What's happening is that the component is just stuck with the initial 'Hello World.' text from state message and not updating with the mocked response message, I'm sure I have to trigger an update or finish a digest cycle of sorts. but I'm not sure how to do that quite yet.

App.js

import React from "react";
import axios from "axios";
import "./App.css";

const App = () => {
  const [message, setMessage] = React.useState("Hello World!");

  React.useEffect(() => {
    const getGreetingFromApi = async () => {
      const apiResponseGreeting = await axios.get("api/hello");
      setMessage(apiResponseGreeting.data);
    };
    getGreetingFromApi();
  });

  return (
    <div className="App">
      <header className="App-header">
        <p>{message}</p>
      </header>
    </div>
  );
};

export default App;

App.test.js

import React from "react";
import ReactDOM from "react-dom";
import { act } from "react-dom/test-utils";

import axios from "axios";
import App from "./App";

jest.mock("axios");

describe("App Component Tests", () => {

    let container;

    beforeEach(() => {
        container = document.createElement("div");
        document.body.appendChild(container);
    });

    afterEach(() => {
        document.body.removeChild(container);
        container = null;
    });

    it("App replaces initial value with greeting response", async () => {
        const mockResponse = { data: "Label Test Text" };
        axios.get.mockResolvedValue(mockResponse);

        let paragraph;

        act(() => {
            ReactDOM.render(<App />, container);
            paragraph = container.querySelector("p");
        });

        expect(paragraph.textContent).toEqual(mockResponse.data);
    });
});

Thank you @diedu for the comments. That pointed me in the right direction. This is the final working test:

it("App replaces initial value with greeting response", async () => {
    const mockResponse = { data: "Label Test Text" };
    axios.get.mockResolvedValue(mockResponse);

    let paragraph;

    await act(async () => {
      await ReactDOM.render(<App />, container);
      paragraph = container.querySelector("p");
    });

    expect(paragraph.textContent).toEqual(mockResponse.data);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM