6

I have 3 source files File1.ts, File2.ts, File3.ts. While executing the Unit tests of File3 I am getting the following Error.

Test suite failed to run

    ReferenceError: Cannot access 'mockMethod1' before initialization

      20 |     __esModule: true,
      21 |     default: jest.fn(),
    > 22 |     method1: mockMethod1,
         |              ^
      23 |     method2: mockMethod2
      24 | }));
      25 | 

Here are the contents of the 3 source files and unit tests for File3.

File1.ts

export default class File1 {
    public element;

    constructor(element) {
        this.element = element;
    }

     method1(inputs) {
         // Logic of Method1.
         return output;
     }

     method2(inputs) {
         // Logic of Method2.
         return output;
     }
}

File2.ts

import File1 from '../Folder1/File1'

export default class File2 {
    public file1Object;

    constructor(element) {
        this.file1Object = new File1(element);
    }

     method1(inputs) {
         // Logic of Method1.
         let out = this.file1Object.method1(inputs);
         // Logic of Method1.
         return output;
     }

     method2(inputs) {
         // Logic of Method2.
         let out = this.file1Object.method2(inputs);
         // Logic of Method2.
         return output;
     }
}

File3.ts

import File2 from '../Folder2/File2'
export default class File3 {
    public file2Object;

    constructor(element) {
        this.file2Object = new File2(element);
    }

     method1(inputs) {
         // Logic of Method1.
         let out = this.file2Object.method1(inputs);
         // Logic of Method1.
         return output;
     }

     method2(inputs) {
         // Logic of Method2.
         let out = this.file2Object.method1(inputs);
         // Logic of Method2.
         return output;
     }
}

File3.test.ts

import File3 from "./File3";
import File2 from "../Folder2/File2";

const mockMethod1 = jest.fn();
const mockMethod2 = jest.fn();

jest.mock('../Folder2/File2', () => ({
    __esModule: true,
    default: jest.fn(),
    method1: mockMethod1,
    method2: mockMethod2
}));

const file3Object = new File3(inputElement);
beforeEach(() => {
    jest.clearAllMocks();
});

test('Method-1 Unit Test', () => {
    mockMethod1.mockReturnValue(expectedOutput);
    let observedOutput = file3Object.method1(inputs);

    expect(observedOutput).toBe(expectedOutput);
})

test('Method-2 Unit Test', () => {
     mockMethod2.mockReturnValue(expectedOutput);
    let observedOutput = file3Object.method2(inputs);
     
     expect(observedOutput).toBe(expectedOutput);
})

I am not sure where I am making the mistake so I am unable to resolve this error. Any suggestions to resolve this issue.

1 Answer 1

16

There are several things that are causing trouble. First, as mentioned in jest docs:

A limitation with the factory parameter is that, since calls to jest.mock() are hoisted to the top of the file, it's not possible to first define a variable and then use it in the factory. An exception is made for variables that start with the word 'mock'. It's up to you to guarantee that they will be initialized on time!

What that means is you need to move around the lines of code to make them look like this:

  // First the mock functions
  const mockMethod1 = jest.fn();
  const mockMethod2 = jest.fn();
  
  // Only then your imports & jest.mock calls
  import File3 from "./File3";
  import File2 from "../Folder2/File2";

  jest.mock('../Folder2/File2', () => ({
    // ...
  }));

The second issue is that you are mocking File2 as if it was exporting method1 and method2, you are not mocking method1 and method2 of the File2 class! Take a look at 4 ways of mocking an ES6 class in jest docs.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh my, you're a life saver. Changing the mock function to be above the import was all I was missing, I've tried a ton of steps and that was the fix.
I was not actually "requiring" the item I was mocking but still could not get the hoisting error to go away until I saw this message. Renaming to start with the word "mock" and moving the creation to the top of the file before all other "require" functions helped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.