jest.mock(..) not working in 'describe' (TypeError: moduleName.split is not a function)

Oliver Watkins picture Oliver Watkins · Apr 16, 2020 · Viewed 7.3k times · Source

jest.mock(..) does not seem to work at the 'describe' level for my tests.

If I have the following :

import React from 'react';
import {someFunction} from "./something/someFile";

describe('Overview Test', () => {

    jest.mock(someFunction);

    test(' snapshot', () => {

    });
});

Then running the 'test' (ie. at the test level), works fine.

But if I run the 'describe' (ie. the describe level or suite level), then I get the following error :

TypeError: moduleName.split is not a function

    at Resolver.resolveModuleFromDirIfExists (A:\frontend\node_modules\jest-resolve\build\index.js:224:30)
    at Resolver.resolveModule (A:\frontend\node_modules\jest-resolve\build\index.js:252:12)

If I have this :

describe('Overview Test', () => {
    test(' snapshot', () => {
        jest.mock(someFunction);
    });
});

Then both ways it does not work.

I have also tried this :

import React from 'react';
import {someFunction} from "./something/someFile";


describe('Overview Test', () => {

    beforeEach(() => {
        jest.mock(someFunction);
    });

    test(' snapshot', () => {

    });
});

And it does not work.

UPDATE

I have also tried this and it does not work :

import React from 'react';
import {someFunction} from "./something/someFile";

    describe('Overview Test', () => {

        jest.mock('./something/someFile', () => {
            return { someFunction: jest.fn(() => "futhissit")};
        });

        test(' snapshot', () => {
            someFunction()
        });
    });

Answer

Christos Lytras picture Christos Lytras · Apr 23, 2020

Jest mock if for mocking modules and the first argument is the moduleName which it has to be a valid module name (inside node_modules or a file path) and not a direct function/module:

jest.mock(moduleName, factory, options)

Mocks a module with an auto-mocked version when it is being required. factory and options are optional.

The error you're getting TypeError: moduleName.split is not a function is because resolveModuleFromDirIfExists tries to split the module name/path and you can see it inside jest-resolve/src/index.ts at line 207.

When you want to test an ES module, you pass the module location for the moduleName and you create a factory using __esModule: true and then create properties with exported functions being mocked using jest.fn():

someFile.js exports the someFunction:

module.exports.someFunction = () => 'Some function result!';

Mocking someFile.js module using jest.mock()

describe('Overview Test', () => {

  // Mock the module and its functions
  jest.mock('./someFile', () => ({
    __esModule: true,
    someFunction: jest.fn(() => 'Mocked someFunction!')
  }));

  // Import the function from the mocked module
  const { someFunction } = require('./someFile');

  test('snapshot', () => {
    // Execute the mocked function
    const someResult = someFunction();

    // Expect to return the mocked value
    expect(someResult).toBe('Mocked someFunction!');
  });

});

You have to import the mocked modules after the jest.mock module mocking. You can create a jest.setup.js and configure it using setupFilesAfterEnv that can have your mocks inside it and then just import the modules like normal at the top of the test files.