使用 Jest 时使节点缓存无效

Posted

技术标签:

【中文标题】使用 Jest 时使节点缓存无效【英文标题】:Invalidate node cache when using Jest 【发布时间】:2018-06-11 01:13:48 【问题描述】:

我有一个包含 process.env 属性的对象的文件:

env.js

console.log('LOADING env.js');

const 
  PROXY_PREFIX = '/api/',
  USE_PROXY = 'true',
  APP_PORT = '8080',
  API_URL = 'https://api.address.com/',
  NODE_ENV = 'production',
 = process.env;

const ENV = 
  PROXY_PREFIX,
  USE_PROXY,
  APP_PORT,
  API_URL,
  NODE_ENV,
;

module.exports.ENV = ENV;

现在我尝试用不同的process.env 属性测试这个文件:

env.test.js

const envFilePath = '../../config/env';

describe('environmental variables', () => 
  const OLD_ENV = process.env;

  beforeEach(() => 
    process.env =  ...OLD_ENV ;
    delete process.env.NODE_ENV;
  );

  afterEach(() => 
    process.env = OLD_ENV;
  );

  test('have default values', () => 
    const  ENV  = require(envFilePath);
    expect(ENV).toMatchSnapshot();
  );

  test('are string values (to avoid casting errors)', () => 
    const  ENV  = require(envFilePath);
    Object.values(ENV).forEach(val => expect(typeof val).toEqual('string'));
  );

  test('will receive process.env variables', () => 
    process.env.NODE_ENV = 'dev';
    process.env.PROXY_PREFIX = '/new-prefix/';
    process.env.API_URL = 'https://new-api.com/';
    process.env.APP_PORT = '7080';
    process.env.USE_PROXY = 'false';

    const  ENV  = require(envFilePath);

    expect(ENV.NODE_ENV).toEqual('dev');
    expect(ENV.PROXY_PREFIX).toEqual('/new-prefix/');
    expect(ENV.API_URL).toEqual('https://new-api.com/');
    expect(ENV.APP_PORT).toEqual('7080');
    expect(ENV.USE_PROXY).toEqual('false');
  );
);

不幸的是,即使我尝试在每个测试中分别加载文件,文件也只加载一次,导致第三次测试失败:

Expected value to equal:
  "dev"
Received:
  "production"

附:当我单独运行测试时它不会失败。

我也知道 env.js 只加载一次,因为 console.log('LOADING env.js'); 只被触发一次。

我试图使节点缓存失效,例如:

  beforeEach(() => 
    delete require.cache[require.resolve(envFilePath)];
    process.env =  ...OLD_ENV ;
    delete process.env.NODE_ENV;
  );

但在每次测试之前require.cache 是空的,所以似乎 Jest 以某种方式负责导入文件。

我也尝试运行yarn jest --no-cache,但没有帮助。

所以我想要的是在每次测试之前加载 env.js,这样我就可以测试它在不同节点环境变量下的表现。

jest@^22.0.4

【问题讨论】:

您使用的是哪个版本的jest @Prakashsharma 22.0.4 尝试在beforeEach 中使用jest.resetModules()。 facebook.github.io/jest/docs/en/… @Prakashsharma 谢谢你!发表答案,我会接受。奇怪的是我错过了。 【参考方案1】:

您可以在beforeEach方法中使用jest.resetModules()来重置已经需要的模块

beforeEach(() => 
  jest.resetModules()
  process.env =  ...OLD_ENV ;
  delete process.env.NODE_ENV;
);

【讨论】:

【参考方案2】:

您可以使用jest.isolateModules(fn) 单独要求模块,而不是重置所有模块。

例如:

test('are string values (to avoid casting errors)', () => 
  jest.isolateModules(() => 
    const  ENV  = require(envFilePath);
    Object.values(ENV).forEach(val => expect(typeof val).toEqual('string'));
  );
);

【讨论】:

以上是关于使用 Jest 时使节点缓存无效的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Jest 不让我使用节点测试环境,即使他们自己更改了它?

使用 Jest 测试时未定义全局节点配置变量

如何在带有 vuetify 和 vuex 的 Vuejs 项目中使用 Jest?节点模块和 Vuetify 问题

一致性哈希算法——虚拟节点

笑话:节点模块依赖使用导入语句并导致测试崩溃

如何在触摸释放时使 IBAction 方法无效