I am trying to use jest to mock the return value of a hook used by a React component, but I can't get it to work. Consider the price tag component. All it does is render the price returned from the usePrice
hook.
In usePrice.ts
export default function usePrice() { return 1337; }
In PriceTag.tsx
:
import React from 'react'; import usePrice from './usePrice'; export default function PriceTag() { const price = usePrice(); return <p>Price: {price}</p> }
In the test, I'm asserting that the correct price is shown. Since I want to create several tests for this component, the setPrice
helper is used to set the next return value for every test.
In __mocks__/usePrice.ts
let price = 58008; export function setPrice(newPrice) { price = newPrice; } export default function usePrice() { return price; }
In PriceTag.test.tsx
import { render } from '@testing-library/react'; import React from 'react'; import PriceTag from './PriceTag'; import { setPrice } from './__mocks__/usePrice'; jest.mock('./usePrice'); describe('PriceTag', () => { it('renders the price', () => { setPrice(100); const { getByText } = render(<PriceTag />); const textEl = getByText('Price: 100'); expect(textEl).toBeInTheDocument(); }); });
When I run the test I get the following failure:
TestingLibraryElementError: Unable to find an element with the text: Price: 100. This could be because the text is broken up by multiple elements. In this case, you can pro vide a function for your text matcher to make your matcher more flexible. <body> <div> <p> Price: 58008 </p> </div> </body> 11 | const { getByText } = render(<PriceTag />); 12 | > 13 | const textEl = getByText('Price: 100'); | ^ 14 | 15 | expect(textEl).toBeInTheDocument(); 16 | });
I can see that the mock is used since 58008
is rendered in the DOM. However, I expect 100
to be returned. I believe this is due to how Jest hoists variables, but it would be very useful if I could get this to work.
This code is directly inspired by their example for mocking the fs
module: https://jestjs.io/docs/manual-mocks#examples