Testing Mock Async Deta Fetching in React Components with useEffect and useState

Asked
Active3 hr before
Viewed126 times

9 Answers

usestateuseeffectasynctestingreact
90%

How is a crossword clue to be interpreted when it contains (… includes part of #-Direction)? ,Connect and share knowledge within a single location that is structured and easy to search., Why did the Buddha contradict about His teachings in these two different suttas?

Pretag
 Pretag team - issue, fix, solve, resolve
88%

After an asynchronous fetch request, the hook is updated with new data data2.,After an asynchronous fetch request, the hook is updated with data data1 and isLoading is false.,After an asynchronous fetch request, when a fresh response is received, the data is updated to data4.

Pretag
 Pretag team - issue, fix, solve, resolve
72%

Pretag
 Pretag team - issue, fix, solve, resolve
65%

Instead of calling real APIs in all your tests, you can mock requests with dummy data. Mocking data fetching with “fake” data prevents flaky tests due to an unavailable backend, and makes them run faster. Note: you may still want to run a subset of tests using an “end-to-end” framework that tells whether the whole app is working together.,We can write tests for this component by leveraging Jest’s timer mocks, and testing the different states it can be in.,A common way to do it is to use a pair of beforeEach and afterEach blocks so that they’ll always run and isolate the effects of a test to itself:

import {
   unmountComponentAtNode
} from "react-dom";

let container = null;
beforeEach(() => {
   // setup a DOM element as a render target
   container = document.createElement("div");
   document.body.appendChild(container);
});

afterEach(() => {
   // cleanup on exiting
   unmountComponentAtNode(container);
   container.remove();
   container = null;
});
load more v
75%

When the component that we want to test consumes data from a context in the upper level of the app tree, what we need is to mock the return value from that context, as we need to see current component behavior, based on certain values of the context. This can be done by mocking the context module using jest.mock() function. ,Another important thing to note is that if we mock the context module, we don’t need to include it in the component’s render, as the test will understand that AuthProvider has also been changed by a fake provider.,The object that we’re mocking should match with the one received from a real call. That way, we can expect normal behavior in the component test. After this, the test can continue by wrapping the render in the act() function and checking the presence of certain things in the document.

const MainPage = () => (
<div className="danger" data-testid="Div::Loading">
   Loading...
</div>
);
load more v
40%

In the examples, I'm going to call getResource which is a function that returns a Promise. I do this both because I want to hide the fetching logic and because it's then easier to test my component—I jest.mock the import,Fetching data is one of those things that I do all the time in my code. I've decided to take a look at ways to streamline it as much as possible.,We converted our class into a function. That's because Hooks can be used only within a functional component.

import React from "react";
import {
   getResource
} from "./api";

class FetchOneResource extends React.Component {
   state = {
      valueA: null
   };

   async componentDidMount() {
      const valueA = await getResource("A");
      this.setState({
         valueA
      });
   }

   render() {
      const {
         valueA
      } = this.state;

      return valueA == null ? "Loading..." : valueA;
   }
}
load more v
22%

When using React Testing Library, use async utils like waitFor and findBy...,Common mistakes when using React Testing Library,React Testing Library provides async utilities to for more declarative and idiomatic testing.

Warning: An update to <SomeComponent> inside a test was not wrapped in act(...).
   When testing, code that causes React state updates should be wrapped into act(...)
load more v
60%

The following code snippet constitutes a simple custom hook to perform a GET request with axios.,Frontend developer who likes to learn by teaching,The problem is known and the community is working to solve it. Even Dan Abramov confirms that testing hooks is not 100% ready, yet.

// useFetch.js
import {
   useState,
   useEffect
} from "react";
import axios from "axios";

// custom hook for performing GET request
const useFetch = (url, initialValue) => {
   const [data, setData] = useState(initialValue);
   const [loading, setLoading] = useState(true);
   useEffect(() => {
      const fetchData = async function() {
         try {
            setLoading(true);
            const response = await axios.get(url);
            if (response.status === 200) {
               setData(response.data);
            }
         } catch (error) {
            throw error;
         } finally {
            setLoading(false);
         }
      };
      fetchData();
   }, [url]);
   return {
      loading,
      data
   };
};

export default useFetch;
load more v
48%

Use the setupServer function from msw to mock an API request that our tested component makes.,testing-library-selector,eslint-plugin-testing-library

Pretag
 Pretag team - issue, fix, solve, resolve

Other "usestate-useeffect" queries related to "Testing Mock Async Deta Fetching in React Components with useEffect and useState"