Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
884 views
in Technique[技术] by (71.8m points)

jestjs - Jest - getting error when mocking FS modules and calling config module

I'm writing unit tests with Jest trying to test a module which uses FS.

The module file:

import fs from 'fs';
import logger from './logger.utils';

export const getNumberOfFiles = async (targetDir: string): Promise<number> => {
  // get number of folders
  logger.info(`getNumberOfFiles from ${targetDir}/${fileName}`);
  const numberOfFiles = await fs.readdirSync(targetDir);
  return numberOfFiles.length;
};

Test file

import fs from 'fs';
import { getNumberOfFiles } from '../../src/utils/fs.utils';

jest.mock('fs');

describe('fs.utils', () => {
  describe('getNumberOfFiles', () => {
    it('Should return number', async () => {
      fs.readdirSync = jest.fn();
      const readdirSyncMock = fs.readdirSync = jest.fn();
      readdirSyncMock.mockResolvedValue([1, 2, 3]);

      const result = await getNumberOfFiles('targetDir');
      expect(result).toEqual(3);
      expect(readdirSyncMock.mock.calls.length).toEqual(1);
    });
  });
});

When I run the test file, I get the following error:

Config file ..../config/runtime.json cannot be read. Error code is: undefined. Error message is: Cannot read property 'replace' of undefined

  1 | const cheggLogger = require('@chegg/logger');
  2 | import loggingContext from './loggingContext';
> 3 | import config from 'config';
    | ^
  4 | import os from 'os';
  5 | import constants from '../../config/constants';
  6 | 

  at Config.Object.<anonymous>.util.parseFile (node_modules/config/lib/config.js:789:13)
  at Config.Object.<anonymous>.util.loadFileConfigs (node_modules/config/lib/config.js:666:26)
  at new Config (node_modules/config/lib/config.js:116:27)
  at Object.<anonymous> (node_modules/config/lib/config.js:1459:31)
  at Object.<anonymous> (src/utils/logger.utils.ts:3:1)

Content of logger.utils.ts

const internalLogger = require('internalLogger');
import loggingContext from './loggingContext';
import config from 'config';
import os from 'os';
import constants from '../../config/constants';

const logger = internalLogger.createLogger({
  level: config.get(constants.LOG_LEVEL)
});

export default logger;

I assume that config is using FS, and once I mock the module, it fails. How can I resolve this? Please advise

question from:https://stackoverflow.com/questions/65871990/jest-getting-error-when-mocking-fs-modules-and-calling-config-module

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'm guessing the problem comes from config also using the fs api but you are now mock entire module fs which makes all methods should be mocked before using.

But I have an idea for you by using jest.doMock which you can provide a factory for each test and just mock only method we need. Here is a draft idea:

describe('fs.utils', () => {
  describe('getNumberOfFiles', () => {
    it('Should return number', async () => {

      jest.doMock('fs', () => ({
        // Keep other methods still working so `config` or others can use
        // so make sure we don't break anything
        ...jest.requireActual('fs'),
        readdirSync: jest.fn(pathUrl => {
          // Mock for our test path since `config` also uses this method :(
          return pathUrl === 'targetDir' ? Promise.resolve([1, 2, 3]) : jest.requireActual('fs').readdirSync(pathUrl)
        })
      }));
      
      // One of the thing we should change is to switch `require` here
      // to make sure the mock is happened before we actually require the code
      // we can also use `import` here but requires us do a bit more thing
      // so I keep thing simple by using `require`
      const {getNumberOfFiles} = require('../../src/utils/fs.utils');
  
      const result = await getNumberOfFiles('targetDir');
      expect(result).toEqual(3);
      // you might stop assert this as well
      // expect(readdirSyncMock.mock.calls.length).toEqual(1);
    });
  });
});

Just also want to check, if you created a config file as described here: https://www.npmjs.com/package/config#quick-start


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...