#jestjs #fs
#jestjs #fs
Вопрос:
Я пишу модульные тесты с помощью Jest, пытаясь протестировать модуль, который использует FS.
Файл модуля:
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;
};
Тестовый файл
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);
});
});
});
Когда я запускаю тестовый файл, я получаю следующую ошибку:
Файл конфигурации …./config/runtime.json не может быть прочитан. Код ошибки: не определено. Сообщение об ошибке: не удается прочитать свойство ‘replace’ неопределенного
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)
Содержимое 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;
Я предполагаю, что config использует FS, и как только я издеваюсь над модулем, он выходит из строя.
Как я могу решить эту проблему? Пожалуйста, сообщите
Ответ №1:
Я предполагаю, что проблема возникает config
также из-за использования fs
api, но теперь вы создаете макет всего модуля fs
, из-за чего все методы должны быть высмеяны перед использованием.
Но у меня есть идея для вас, используя jest.doMock
которую вы можете предоставить фабрику для каждого теста и просто имитировать только тот метод, который нам нужен. Вот черновик идеи:
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);
});
});
});
Также хочу проверить, создали ли вы файл конфигурации, как описано здесь: https://www.npmjs.com/package/config#quick-start
Комментарии:
1. Попробовал ваше решение, получив эту ошибку
Configuration property "LOG_LEVEL" is not defined
из файла регистратора. В качестве конфигурации невозможно использовать модуль fs.