Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking React custom hook with Jest

I need to mock my custom hook when unit testing React component. I have read few tutorials and stackoverflow answers to this simple task, but without luck to implement it correctly.

My simplest possible setup for single test is as following:

// TestComponent.js

import React from "react";
import useTest from "./useTest";

const TestComponent = () => {
  const { state } = useTest("initial_value");

  return <div>{state}</div>;
};

export default TestComponent;
// useTest.jsx - simple custom hook

import React, { useState } from "react";

const useTest = (initialState) => {
  const [state] = useState(initialState);
  return { state };
};

export default useTest;

// TestComponent.test.jsx - my test case

import React from "react";
import { render } from "@testing-library/react";
import TestComponent from "./TestComponent";

jest.mock("./useTest", () => ({
  useTest: () => "mocked_value",
}));

test("rendertest", () => {
  const component = render(<TestComponent />);
  expect(component.container).toHaveTextContent("mocked_value");
});

So I trying to mock useTest custom hook to return "mocked_value", instead of "initial_value" from real custom hook. But above code just gives me this error:

TypeError: (0 , _useTest.default) is not a function

      3 | 
      4 | const TestComponent = () => {
    > 5 |   const { state } = useTest("initial_value");
        |                     ^
      6 | 
      7 |   return <div>{state}</div>;
      8 | };

I have also tried:

import useTest from './useTest';
// ...
jest.spyOn(useTest, "useTest").mockImplementation(() => "mocked_value");
import useTest from './useTest';
// ...
jest.spyOn(useTest, "useTest").mockReturnValue("mocked_value");

But both gives me error Cannot spy the useTest property because it is not a function; undefined given instead.

How do I implement this test?

like image 328
darx Avatar asked Dec 12 '20 22:12

darx


People also ask

How do you mock a custom hook Jest?

to call jest. mock with the module name and the function to mock the useClientRect hook with a function that returns the mocked values of the hook. import * as hooks from 'module_name'; it('a test', () => { jest. spyOn(hooks, 'useClientRect').

Can you test React Hooks with Jest?

Testing React Hooks with Jest and Enzyme. Jest and Enzyme are tools used for testing React apps. Jest is a JavaScript testing framework used to test JavaScript apps, and Enzyme is a JavaScript testing utility for React that makes it easier to assert, manipulate, and traverse your React components' output.

How do you mock a variable in Jest React?

If you need to mock a global variable for all of your tests, you can use the setupFiles in your Jest config and point it to a file that mocks the necessary variables. This way, you will have the global variable mocked globally for all test suites.

How do you write a test case for custom Hooks?

import { renderHook, act } from '@testing-library/react-hooks'; import useCounter from '../hooks/useCounter'; describe('useCounter', () => { test(`Default value of `count` will be zero`, () => { const { result } = renderHook(() => useCounter()); expect(result. current. count). toBe(0); }); });

How to mock react custom Hook return value with jest?

to mock the useClientRect hook and return the mocked return values with mockImplementation. We can just mock the return values since hooks are pure functions so they don’t commit side effects. To mock React custom hook returned value with Jest, we can call jest.mock.

How do I mock a hook in jest?

The first method is mocking our hook at the top level of our test. Doing so will make this mocking enabled for all tests within this file. We are using jest.mock to do the mocking. As a first parameter, it’s taking the path to the file to mock.

Why do I need to mock a function in jest?

*This post assumes you already have Jest configured in your application. I was using a custom hook in a component that needed to be mocked out in order to properly produce a snapshot test. I chose to mock the this particular function because it was dependent on a part of the DOM that was not available for the hook to be operational.

Why did I mock a function in a custom hook?

I was using a custom hook in a component that needed to be mocked out in order to properly produce a snapshot test. I chose to mock the this particular function because it was dependent on a part of the DOM that was not available for the hook to be operational.


2 Answers

I'm answering to myself. This way it's working:

jest.mock("./useTest", () => ({
  useTest: () => ({ state: 'mocked_value' }),
}));

And if I want to use default export in custom hook:

jest.mock("./useTest", () => ({
  __esModule: true,
  default: () => ({ state: 'mocked_value' }),
}));

Also, if I want to also use setState method in my hook and export it, I can mock it like this:

const mockedSetState = jest.fn();

jest.mock("./useTest", () => ({
  useTest: () => ({ state, setState: mockedSetState }),
}));

And now it's possible to check if setState has been called once:

expect(mockedSetState).toHaveBeenCalledTimes(1);
like image 68
darx Avatar answered Oct 28 '22 08:10

darx


Since you use export default useTest in useTest module, it expects to get that function reference from a default attribute in your mock.

Try this:

jest.mock("./useTest", () => ({
  default: () => "mocked_value",
}));

If you want to avoid confusion, you could try export const useTest = ... in useTest module and then import { useTest } from './useTest' in your component. No need to change your test if using this approach.

like image 1
Kelvin Nguyen Avatar answered Oct 28 '22 08:10

Kelvin Nguyen