用Jest测试process.env

Tom*_*zyk 45 testing environment-variables node.js jestjs

我有一个应用程序依赖于环境变量,如:

const APP_PORT = process.env.APP_PORT || 8080;
Run Code Online (Sandbox Code Playgroud)

我想测试一下例如:

  • APP_PORT可以由节点env变量设置.
  • 或者express应用程序正在设置的端口上运行process.env.APP_PORT

我怎样才能通过Jest实现这一目标?我可以process.env在每次测试之前设置这些变量,还是应该以某种方式模拟它?

zgr*_*een 125

Jest'ssetupFiles是处理这个问题的正确方法,你不需要安装dotenv,也不需要使用任何.env文件来使它工作。

jest.config.js

module.exports = {
  setupFiles: ["<rootDir>/.jest/setEnvVars.js"]
};
Run Code Online (Sandbox Code Playgroud)

.jest/setEnvVars.js

process.env.MY_CUSTOM_TEST_ENV_VAR = 'foo'
Run Code Online (Sandbox Code Playgroud)

就是这样。

  • 如果您需要在每个测试用例的基础上调整环境变量,这实际上不起作用...... (17认同)
  • 这是在玩笑中处理环境变量的最直接的方法,谢谢! (5认同)
  • 我尝试了该线程中提出的大部分解决方案,这是对我有用的解决方案。 (4认同)
  • 我不确定人们对什么感到高兴,因为它显然不适用于任何在导入/需要时由模块读取“process.env”的实际用例。 (4认同)

Tom*_*zyk 60

我这样做的方式可以在这个SO问题中找到.

在每次测试之前重置模块然后在测试中动态导入模块是很重要的:

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

  beforeEach(() => {
    jest.resetModules() // this is important - it clears the cache
    process.env = { ...OLD_ENV };
    delete process.env.NODE_ENV;
  });

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

  test('will receive process.env variables', () => {
    // set the 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 testedModule = require('../../config/env').default

    // ... actual testing
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 请提供完整的回复 (2认同)
  • 如果这对您不起作用,请确保在实际代码中读取env变量时,是在函数/受限范围内进行读取,而不是使全局变量指向process.env.YOUR_VARIABLE。 (2认同)
  • @MEMark您需要创建一个副本以避免改变原始对象(稍后您需要恢复) (2认同)

jah*_*ler 37

另一种选择是jest.config.jsmodule.exports定义后将其添加到文件中:

process.env = Object.assign(process.env, {
  VAR_NAME: 'varValue',
  VAR_NAME_2: 'varValue2'
});
Run Code Online (Sandbox Code Playgroud)

这样就不需要在每个.spec文件中定义环境变量,它们可以全局调整。

  • 当您想要每次测试测试不同的环境变量时,这是一个很好的解决方案。我遇到的大多数其他答案都是全球层面的。谢谢! (2认同)

Emi*_*Emi 37

./package.json

"jest": {
  "setupFiles": [
    "<rootDir>/jest/setEnvVars.js"
  ]
}
Run Code Online (Sandbox Code Playgroud)

./jest/setEnvVars.js

process.env.SOME_VAR = 'value';

Run Code Online (Sandbox Code Playgroud)

  • 可能是我见过的最简单的方法。无需安装 dotenv 包。 (2认同)

Mil*_*kos 10

在测试文件中:

const APP_PORT = process.env.APP_PORT || 8080;
Run Code Online (Sandbox Code Playgroud)

在测试脚本中./package.json

"scripts": {
   "test": "jest --setupFiles dotenv/config",
 }
Run Code Online (Sandbox Code Playgroud)

./env

APP_PORT=8080
Run Code Online (Sandbox Code Playgroud)


Ser*_* C. 7

您可以使用setupFiles笑话配置功能。正如文档所说

运行一些代码以配置或设置测试环境的模块的路径列表。每个setupFile将对每个测试文件运行一次。由于每个测试都在自己的环境中运行,因此这些脚本将在执行测试代码本身之前立即在测试环境中执行。

  1. npm install dotenv 用于访问env变量的dotenv。
  2. .env文件创建到应用程序的根目录,并将此行添加到其中。
#.env
APP_PORT=8080
Run Code Online (Sandbox Code Playgroud)
  1. 创建您的自定义模块文件,其名称为someModuleForTest.js并将此行添加到其中。
//someModuleForTest.js
require("dotenv").config()
Run Code Online (Sandbox Code Playgroud)
  1. jest.config.js像这样更新文件
module.exports = {
  setupFiles: ["./someModuleForTest"]
}
Run Code Online (Sandbox Code Playgroud)
  1. 您可以在所有测试块中访问env的变量。
test("Some test name", () => {
  expect(process.env.APP_PORT).toBe("8080")
})
Run Code Online (Sandbox Code Playgroud)


Rob*_*obW 6

根据组织代码的方式,另一种选择是将环境变量放在运行时执行的函数中。

在此文件中,环境变量是在导入时设置的,并且需要动态require来测试不同的环境变量(如本答案中所述):

const env = process.env.MY_ENV_VAR;

const envMessage = () => `MY_ENV_VAR is set to ${env}!`;

export default myModule;
Run Code Online (Sandbox Code Playgroud)

在此文件中,环境变量在执行时设置envMessage,您应该能够在测试中直接更改 process.env:

const envMessage = () => {
  const env = process.env.MY_VAR;
  return `MY_ENV_VAR is set to ${env}!`;
}

export default myModule;
Run Code Online (Sandbox Code Playgroud)

开玩笑测试:

const vals = [
  'ONE',
  'TWO',
  'THREE',
];

vals.forEach((val) => {
  it(`Returns the correct string for each ${val} value`, () => {
    process.env.MY_VAR = val;

    expect(envMessage()).toEqual(...
Run Code Online (Sandbox Code Playgroud)


Dav*_*ood 6

在我看来,如果您将环境变量的检索提取到一个实用程序中,它会更清晰、更容易理解(如果无论如何都没有设置环境变量,您可能希望包括一个快速失败的检查),然后您可以模拟公用事业。

// util.js
exports.getEnv = (key) => {
    const value = process.env[key];
    if (value === undefined) {
      throw new Error(`Missing required environment variable ${key}`);
    }
    return value;
};

// app.test.js
const util = require('./util');
jest.mock('./util');

util.getEnv.mockImplementation(key => `fake-${key}`);

test('test', () => {...});
Run Code Online (Sandbox Code Playgroud)

  • 太棒了,谢谢你的提示!简单,但有效。 (2认同)

小智 6

稍微扩展一下Serhan C. 的回答......

根据博客文章How to Setup dotenv with Jest Testing - In-depth Explanation,您可以"dotenv/config"直接包含在 中setupFiles,而无需创建和引用调用require("dotenv").config().

即,简单地做

module.exports = {
    setupFiles: ["dotenv/config"]
}
Run Code Online (Sandbox Code Playgroud)

  • 最好的解决方案在这里!值得一提的是,在 `jest.config.ts` 中,如果您希望它在所有测试之前运行一次,而不是在每个测试文件之前重置它们,您可以在 `globalSetup` 键而不是 `setupFiles` 键下使用它 (2认同)

小智 5

你可以将其导入到 jest.config.js 中

require('dotenv').config()
Run Code Online (Sandbox Code Playgroud)

这对我有用


Str*_*ch0 5

要基于 @HenryTipantu\xc3\xb1a 的建议,在 jest.config.js 中导入 dotenv 并在配置路径中使用 .env.test 文件

\n
require('dotenv').config({\n  path: '.env.test'\n})\n
Run Code Online (Sandbox Code Playgroud)\n