Home > Enterprise >  Received value must be a mock or spy function when mocking a class
Received value must be a mock or spy function when mocking a class

Time:10-18

I am writing a test to check that one method is called when the callback is executed. However, it is getting me this error.

expect(received).toHaveBeenCalled()

Matcher error: received value must be a mock or spy function

Received has value: undefined

According to Jest automatic class mocks adding the line jest.mock(...) should be enough to get a mocked class, but it seems that I am missing something here.

This is my test file:

import { render, fireEvent } from "@testing-library/react";
import Grid from "../../components/Grid";
import DetectFibonacciUseCase from "../../useCases/DetectFibonacciUseCase";

jest.mock("../../useCases/DetectFibonacciUseCase");

describe("GridComponent", () => {
    test("Should've called the run method when the callback is executed", () => {
       const { getByTestId } = render(<Grid />);
       const firstCellButton = getByTestId("cell-testid-0-0");

       fireEvent.click(firstCellButton);

       expect(DetectFibonacciUseCase.run).toHaveBeenCalled();
    });
});

The callback function looks like this, and it is actually being executed:

const calculateNewValues = (row, column) => {
    const updatedCells = cells.map((cell) => {
        cell.value = cell.row === row || cell.column === column
          ? cell.value   1
          : cell.value;
        cell.color = cell.row === row || cell.column === column ? ColorConstants.yellow : cell.color;
        return cell;
    });

    const detectFibonacciUseCase = new DetectFibonacciUseCase(
        MINIMUM_CONSECUTIVE_APPAREANCES
    );
    const cellsWithFibonacci = detectFibonacciUseCase.run(updatedCells);
    cellsWithFibonacci.forEach((cellWithFibonacci) => {
      const cellToUpdateIndex = updatedCells.findIndex(
        (cell) =>
          cell.row === cellWithFibonacci.row &&
          cell.column === cellWithFibonacci.column
      );
      updatedCells[cellToUpdateIndex].color = ColorConstants.green;
      updatedCells[cellToUpdateIndex].value = 1;
    });

    setCells(updatedCells);
    removeColorsAfterTimeout(updatedCells);
};

I've also tried to use the mockImplementation method, but with no luck at all. Any suggestion is well-received.

Jest version: 26.6.0 React version: 17.0.2 React-testing-library version: ^12.1.2

CodePudding user response:

The run method is called by an instance of the DetectFibonacciUseCase class, not by the class itself.

While the Jest automock will work as expected, you need to access the mock class instance to check if the run function has been called.

const mockDetectFibonacciUseCaseInstance = DetectFibonacciUseCase.mock.instances[0];
expect(mockDetectFibonacciUseCaseInstance.run).toHaveBeenCalled();
  • Related