I am trying to use jest to mock the return value of a hook used by a React component, but 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 | });
The mock is being 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