Consider we have the usePost
custom hook. The hook calls an API and returns a post.
const usePost = () => {
const [post, setPost] = useState();
fetch('my-api/posts/1')
.then(response => response.json())
.then(json => setPost(json));
return post;
}
We also have the Post
component, which simply renders the post title.
function Post() {
const post = usePost();
return <div>{post?.title}</div>
}
Now I'd like to test the post component. I would like the test to not make any API calls. It is possible to achieve this with jest by using their mocks.
import { render } from '@testing-library/react';
import usePost from './usePost';
import Post from './Post'
jest.mock('./usePost');
const mockedUsePost = usePost as Jest.Mock;
it('shows the post title', async () => {
const post = { title: 'My post' }
mockedUsePost.mockImplementation(() => post);
const { findByText } = render(<Post />)
expect(await findByText(/My post/)).toBeInTheDocument();
})
However I don't like this approach. I do not want to rely on jest mocks to test my components. I would like to instead create an inline mock implementation of the hook which I pass as a prop.
import { render } from '@testing-library/react';
import usePost from './usePost';
import Post from './Post'
it('shows the post title', async () => {
const post = { title: 'My post' }
const useMockedPost = () => post
const { findByText } = render(<Post usePost={useMockedPost} />)
expect(await findByText(/My post/)).toBeInTheDocument();
})
Is there any negative side effects of doing so? Is it bad practice doing so?
I've extensively searched the web for answers but haven't found anything really helpful.
I'm thinking it might violate one of the hook rules. Namely it says "Don’t call Hooks inside loops, conditions, or nested functions.". One could argue that it is called in a condition as the component may be conditionally rendered. I would argue this will not be a problem since we never change the hook again during runtime.
Top comments (0)