Mock a module that returns a function and test that this function was called

Viewed 40

I want to test a React component that, internally, uses a custom hook (Jest used). I successfully mock this hook but I can't find a way to test the calls on the functions that this hook returns.

Mocked hook

const useAutocomplete = () => {
  return {
    setQuery: () => {}
  }
}

React component

import useAutocomplete from "@/hooks/useAutocomplete";

const MyComponent = () => {
  const { setQuery } = useAutocomplete();

  useEffect(() => {
    setQuery({});
  }, [])
  ...
}

Test

jest.mock("@/hooks/useAutocomplete");

it("sets the query with an empty object", () => {
  render(<MyComponent />);

  // I want to check the calls to setQuery here
  // e.g. mockedSetQuery.mock.calls
});

CURRENT SOLUTION

I currently made the useAutocomplete hook an external dependency:

import useAutocomplete from "@/hooks/useAutocomplete";

const MyComponent = ({ autocompleteHook }) => {
  const { setQuery } = autocompleteHook();

  useEffect(() => {
    setQuery({});
  }, [])
  ...
}

MyConsole.defaultProps = {
 autocompleteHook: useAutocomplete
}

And then I test like this:

const mockedSetQuery = jest.fn(() => {});

const useAutocomplete = () => ({
  setQuery: mockedSetQuery,
});

it("Has access to mockedSetQuery", () => {
  render(<MyComponent autocompleteHook={useAutocomplete} />);

  // Do something

  expect(mockedSetQuery.mock.calls.length).toBe(1);  
})
1 Answers

You can mock the useAutocomplete's setQuery method to validate if it's invoked.

jest.mock("@/hooks/useAutocomplete");

it("sets the query with an empty object", () => {
  const useAutocompleteMock = jest.requireMock("@/hooks/useAutocomplete");
  const setQueryMock = jest.fn();
  useAutocompleteMock.setQuery = setQueryMock;
  render(<MyComponent />);

  // The mock function is called twice
  expect(setQueryMock.mock.calls.length).toBe(1);

});
Related