Jest automock fails: TypeError: fs.readdirSync is not a function

Viewed 350

I'm trying to produce an auto-mock of the 'fs' module and then extend it, but my implementations are not working:

// /home/user/cp/projectName/__mocks__/fs.js

const fs = jest.createMockFromModule('fs');

function readdirSync(fileName) {
  console.log(`The file name passed to this fake fs.readdirSync method is: ${fileName}`);

  return 'return value from fake fs.readdirSync';
}

function specialMethod() {
  return 'returned from the special method';
}

fs.readdirSync = readdirSync;
fs.specialMethod = specialMethod;

exports = fs;

The above __mocks__ folder is a sibling of the node_modules folder.

Running the test file seems to ignore the above mock module:

// /home/user/cp/projectName/src/captureCallData/__tests__/unit.test.ts

/* eslint-disable no-undef */
jest.mock('fs');
const fs = require('fs');

test('test fs.specialMethod', () => {
  const result = fs.specialMethod();
});

function useFsInternally(fakeFileName: string) {
  return fs.readdirSync(fakeFileName);
}

test('test mocking functionality', () => {
  const result: string = useFsInternally('testInput');

  expect(result).toStrictEqual('wrong value');
});

test fs.specialMethod

    TypeError: fs.specialMethod is not a function

      10 | 
      11 | test('test fs.specialMethod', () => {
    > 12 |   const result = fs.specialMethod();
         |                     ^
      13 | });
      14 | 
      15 | function useFsInternally(fakeFileName: string) {

      at Object.<anonymous> (src/captureCallData/__tests__/unit.test.ts:12:21)

  ● test mocking functionality

    TypeError: fs.readdirSync is not a function

      14 | 
      15 | function useFsInternally(fakeFileName: string) {
    > 16 |   return fs.readdirSync(fakeFileName);
         |             ^
      17 | }
      18 | 
      19 | test('test mocking functionality', () => {

      at useFsInternally (src/captureCallData/__tests__/unit.test.ts:16:13)
      at Object.<anonymous> (src/captureCallData/__tests__/unit.test.ts:20:26)                             

Is this configuration incorrect? What step is being missed?

Here are the relevant libraries:

"dependencies": {
    "typescript": "^3.9.7"
  },
  "devDependencies": {
    "@types/jest": "^26.0.9",
    "jest": "^26.2.2",
    "ts-jest": "^26.1.4"
  }

Also Tried

  • import and export syntax instead of require(). In this case the actual fs module appeared to import instead of the mock:
    src/captureCallData/__tests__/unit.test.ts:12:21 - error TS2339: Property 'specialMethod' does not exist on type 'typeof import("fs")'.

    12   const result = fs.specialMethod();
                           ~~~~~~~~~~~~~
    src/captureCallData/__tests__/unit.test.ts:20:9 - error TS2322: Type 'string[]' is not assignable to type 'string'.

    20   const result: string = useFsInternally('testInput');
               ~~~~~~

1 Answers

exports is local variable that is initially equal to module.exports and contains a reference to export object. It is supposed to be mutated, not reassigned. exports = fs only replaces the value of local variable and doesn't affect exported value.

It should be either

module.exports = fs;

or

Object.assign(exports, fs);
Related