4

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

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Emric Månsson
  • 495
  • 6
  • 15

1 Answers1

7

I believe the issue you're seeing is due to the fact that you're importing the mock itself.

import { setPrice } from './__mocks__/usePrice';

Jest expects you to import the actual module. Try changing it to

import { setPrice } from './usePrice';
Kevin Sjöberg
  • 2,261
  • 14
  • 20