Reputation: 20230
I'm currently writing a React component in Typescript which makes use of a axios-hooks hook called useAxios. An example of this hook in use is here:
export const App = () => {
const [{ data, loading, error }, refetch] = useAxios(
"https://api.myjson.com/bins/820fc"
);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error!</p>;
return (
<div>
<button onClick={e => refetch()}>refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
const rootElement = document.getElementById("root");
render(<App />, rootElement);
I'm trying to figure out how to write a test where I can mock the useAxios hook. I've tried creating a mock of the underlying axios component but I cant get this working:
import React from "react"
import { render } from "@testing-library/react"
import { Test } from "../test"
import useAxios from "axios-hooks"
jest.mock("axios-hooks")
const mockedAxios = useAxios as jest.Mocked<typeof useAxios>
it("Displays loading", () => {
// How to mock the return values in the following line?
// mockedAxios.
const { getByText } = render(<Test />)
expect(getByText("Loading...")).toBeDefined()
})
I know that I shouldn't have to mock axios which is the underlying dependency, I should be able to mock useAxios, but I though I'd try anyhow.
I realise that this question has been mentioned many times on SO, but I can find a solution to this particular use case.
Any help greatly appreciated!
Upvotes: 2
Views: 5155
Reputation: 19
I had to jump through some additional hoops to get the compiler happy with the () => undefined
parameter. I'm not a fan of the double as
, but I'm not sure how to make it less verbose as I'm new to TS.
import * as useAxios from 'axios-hooks';
import { AxiosPromise } from 'axios';
import React from 'react';
import Test from 'components/Test';
import { render } from '@testing-library/react';
jest.mock('axios-hooks');
const mockedUseAxios = useAxios as jest.Mocked<typeof useAxios>;
it('renders a loading message', async () => {
mockedUseAxios.default.mockImplementation(() => [
{
data: [],
loading: true,
error: undefined,
},
(): AxiosPromise => (undefined as unknown) as AxiosPromise<unknown>,
]);
const { getByText } = render(<Test />);
expect(getByText('Loading...')).toBeDefined();
});
Upvotes: 1
Reputation: 20230
I figured out how to do this myself. To test the custom hook I did the following:
import * as useAxios from "axios-hooks"
jest.mock("axios-hooks")
const mockedAxios = useAxios as jest.Mocked<typeof useAxios>
it("Displays loading message", async () => {
// Explicitly define what should be returned
mockedAxios.default.mockImplementation(() => [
{
data: [],
loading: true,
error: undefined
},
() => undefined
])
const { getByText } = render(<Test />)
expect(getByText("Loading...")).toBeDefined()
})
Upvotes: 2
Reputation: 82136
Mock the module and setup the expected result of useAxios
per test e.g.
jest.mock('axios-hooks');
import useAxios from 'axios-hooks';
test('App displays loading when request is fetching', () => {
useAxios.mockReturnValue(Promise.resolve({ loading: true }));
// mount component
// Verify "Loading" message is rendered
});
Upvotes: 1