Introduction
In this article we will cover the basic usage of testing useQuery
hook from tanstack/react-query
library, along with how to test it using jest and react-testing-library.
Example
The following code is an example of a React application that displays a list of users fetched from an API using the react-query
library.
The UserList
component uses the useUsersQuery
hook, which is defined in the usersQuery.js
file, to fetch the data and display it in a list.
The App
component wraps the UserList
component in a QueryClientProvider
from react-query
, which allows the query to be managed by the QueryClient
.
import "../index.css";
import { QueryClient, QueryClientProvider } from "react-query";
import { useUsersQuery } from "./usersQuery";
function UserList() {
const { data, status } = useUsersQuery();
if (status === "loading") {
return <div data-testid="users-loading">Loading...</div>;
}
if (status === "error") {
return <div data-testid="users-error">Error!</div>;
}
return (
<ul data-testid="users-wrapper">
{data.map((user) => (
<li key={user.id} data-testid={`user-${user.id}`}>
{user.name}
</li>
))}
</ul>
);
}
const client = new QueryClient();
function App() {
return (
<QueryClientProvider client={client}>
<UserList />
</QueryClientProvider>
);
}
export default App;
import { useQuery } from "react-query";
export const useUsersQuery = () => {
const results = useQuery(["Users"], () => {
return fetch("https://gorest.co.in/public/v2/users").then((res) =>
res.json()
);
});
return results;
};
Testing
The provided users.test.js
file contains tests for the Users
component, which is the default export from the Users.js
file. The tests use the @testing-library/react
library to render the component and make assertions about its rendered output.
import { QueryClient, QueryClientProvider } from "react-query";
import { render, screen } from "@testing-library/react";
import Users from "../Users";
import { useUsersQuery } from "../usersQuery";
const mockedUseUsersQuery = useUsersQuery;
jest.mock("../usersQuery");
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
const wrapper = ({ children }) => (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
export default wrapper;
describe("Users component", () => {
it("Displays the loading view", () => {
mockedUseUsersQuery.mockImplementation(() => ({
status: "loading",
}));
render(<Users />, { wrapper });
expect(screen.getByTestId("users-loading")).toBeInTheDocument();
expect(screen.getByText(/Loading.../i)).toBeVisible();
});
it("Displays the error message", () => {
mockedUseUsersQuery.mockImplementation(() => ({
status: "error",
}));
render(<Users />, { wrapper });
expect(screen.getByTestId("users-error")).toBeInTheDocument();
expect(screen.getByText(/Error!/i)).toBeVisible();
});
it("should render users list", () => {
mockedUseUsersQuery.mockImplementation(() => ({
status: "success",
data: [
{ id: 1, name: "test user" },
{ id: 2, name: "test user2" },
],
}));
render(<Users />, { wrapper });
expect(screen.getByTestId("users-wrapper")).toBeInTheDocument();
expect(screen.getByTestId("user-1")).toBeInTheDocument();
expect(screen.getByTestId("user-1").textContent).toEqual("test user");
expect(screen.getByTestId("user-2")).toBeInTheDocument();
expect(screen.getByTestId("user-2").textContent).toEqual("test user2");
});
});
- The first test,
Displays the loading view
, mocks theuseUsersQuery
hook to return a loading status and then renders theUsers
component. It then uses thegetByTestId
function from@testing-library/react
to check that the loading view is displayed. - The second test,
Displays the error message
, works in a similar way, but mocks theuseUsersQuery
hook to return an error status instead of a loading status. It then checks that the error message is displayed. - The third test,
should render users list
, mocks theuseUsersQuery
hook to return a success status and some data, and then checks that the list of users is rendered correctly.
Running the above test file, by executing the following command:
npm run test
// OR
yarn test
we will get the following results:

$ react-scripts test --coverage --watchAll=false users.test.js
PASS src/users/__tests__/users.test.js
Users component
✓ Displays the loading view (21 ms)
✓ Displays the error message (4 ms)
✓ should render users list (3 ms)
Photo from Unsplash.
what if i have multiple useQueryhandlers in the same page?