Reputation: 13539
I am attempting to test a component that uses the useAsync hook using the @testing-library/react .
If I use jest.mock on the TestAPI module, followed by getTest.mockResolvedValueOnce(testArray); on the getTest function then I would expect the mock to correctly return the test values.
Test :
import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import TestPanel from "./TestPanel";
import { getTest } from "./TestAPI";
jest.mock("./TestAPI");
it("renders cards correctly", async () => {
const testArray = ["hi there"];
getTest.mockResolvedValueOnce(testArray);
render(<TestPanel />);
expect(getTest).toHaveBeenCalledTimes(1);
expect(getTest).toHaveBeenCalledWith();
await waitFor(() => expect(screen.getByText("hi there")).toBeInTheDocument());
});
Component to be tested :
import React from "react";
import { useAsync } from "react-async-hook";
import { getTest } from "./TestAPI";
export default function TestPanel() {
const { result: elems } = useAsync(getTest, []);
return (
<div>
{elems &&
elems.map((elem) => {
return <div>{elem}</div>;
})}
</div>
);
}
API call :
import React from "react";
import axios from "axios";
export async function getTest(): Promise {
const response = await axios.get("/someservice");
return response.data || [];
}
However if I run the test then an exception is thrown saying that the "elems.map" is undefined.
On closer inspection it seems that the elems is a promise.
Is there something that I am doing wrong?
Upvotes: 3
Views: 1636
Reputation: 13843
These are your issues: react-async-hook & jest
Here react-async-hook
uses instanceof Promise
but Jest.mockResolvedValueOnce
returns not a real JS Promise
, but a promise-like object. So the useAsync()
treats the mock as a sycn function.
The solution is to use mockImplementationOnce
instead of mockResolvedValueOnce
getTest.mockImplementation(async () => testArray)
From the docs:
mockFn.mockResolvedValueOnce(value)
Syntactic sugar function for:
jest.fn().mockImplementationOnce(() => Promise.resolve(value));
But, sadly, it's not just a syntactic sugar.
Upvotes: 1
Reputation: 697
i think you should mock your return from the useAsync hook itself.
jest.mock("path/to/useAsync", () => ({
result: ["test"]
}));`
Upvotes: 0