在玩笑中模拟特定的配置值

问题描述

我有以下 default/config.js 文件

/* eslint-disable @typescript-eslint/no-var-requires */
require('dotenv').config({
  path: require('find-config')('.env'),});

module.exports = {
  cronInterval: process.env.CRON_INTERVAL,queueName: process.env.QUEUE_NAME || '',isVisible: process.env.IS_VISIBLE
};

在我的 index.ts 中,我有

import config from 'config';
import * as cron from 'node-cron';

const isVisible = config.get<boolean>('isVisible');
const queueName = config.get<string>('queueName');
const cronInterval = config.get<string>('cronInterval');

function startProcess(queueName) {
    cron.schedule(cronInterval,() => {});
}

// process starts here
if (isVisible) {
  startProcess(queueName);
} else {
  logger.info('Wont start')
}

在我的单元测试中,我想测试 isVisible 的两种情况,同时保持其他配置值不变。

我试过了

describe.only('isVisible',() => {
    beforeEach(() => {
        jest.mock('./../config/default.js',() => ({ 
            isVisible: false
        }));
    })
    it('should not run anything if not visible',() => {
        require('./../src/index');
        const scheduleSpy = jest.spyOn(cron,'schedule');
        expect(scheduleSpy).not.toHaveBeenCalled();
    })
})

这对我不起作用,它不会覆盖 isVisible 的值。

我知道我也可以模拟 config.get 之类的 config.get.mockReturnValue(false) 函数,但这会覆盖 cronIntervalqueueName

解决方法

这是我最近解决类似需求的一种方法(有条件地需要原始模块功能)...

let isVisible = false;

jest.mock('config',() => {
  // Require the original module!
  const originalConfig = jest.requireActual('config');

  return {
    __esModule: true,// for esModules
    get: jest.fn((key: string) => {
      // override result conditionally on input arguments
      if (key === 'isVisible') return isVisible;
      // otherwise return using original behavior
      return originalModule.get(key);
    })
  };
});

然后在您的测试中:

it('isVisible=true',() => {
  isVisible = true;
  // test logic here
});

it('isVisible=false',() => {
  isVisible = false;
  // test logic here
});