测试过程。环境与玩笑

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

const APP_PORT = process.env.APP_PORT || 8080;

我想测试一下,比如:

  • APP_PORT可以通过Node.js环境变量设置。
  • 或者一个Express.js应用程序运行在带有process.env.APP_PORT的端口集上

我如何用Jest实现这一点?我可以在每次测试之前设置这些process.env变量吗?或者我应该以某种方式模拟它吗?

284800 次浏览

我做它的方式可以在这个堆栈溢出问题中找到

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

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


beforeEach(() => {
jest.resetModules() // Most important - it clears the cache
process.env = { ...OLD_ENV }; // Make a copy
});


afterAll(() => {
process.env = OLD_ENV; // Restore old environment
});


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
});
});

如果在运行Jest之前寻找加载环境值的方法,请查找下面的回答。你应该使用setupFiles

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

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

const env = process.env.MY_ENV_VAR;


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


export default myModule;

在这个文件中,环境变量是在envMessage执行时设置的,你应该能够改变process。Env直接在您的测试中:

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


export default myModule;

Jest测试:

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(...

我觉得你也可以试试这个:

const currentEnv = process.env;
process.env = { ENV_NODE: 'whatever' };


// test code...


process.env = currentEnv;

这适用于我,你不需要模块的东西

你可以使用Jest配置的setupFiles特性。如文件上说

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

  1. npm install dotenv dotenv用于访问环境变量。

  2. 创建你的.env文件到你的应用程序的根目录,并添加这一行:

    #.env
    APP_PORT=8080
    
  3. 创建您的自定义模块文件,其名称为someModuleForTest.js,并将以下行添加到其中:

    // someModuleForTest.js
    require("dotenv").config()
    
  4. 像这样更新你的jest.config.js文件:

    module.exports = {
    setupFiles: ["./someModuleForTest"]
    }
    
  5. 您可以访问所有测试块中的环境变量。

    test("Some test name", () => {
    expect(process.env.APP_PORT).toBe("8080")
    })
    

另一个选项是将它添加到jest.config.js文件的module.exports定义之后:

process.env = Object.assign(process.env, {
VAR_NAME: 'varValue',
VAR_NAME_2: 'varValue2'
});

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

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

jest.config.js:

module.exports = {
setupFiles: ["<rootDir>/.jest/setEnvVars.js"]
};

.jest/setEnvVars.js:

process.env.MY_CUSTOM_TEST_ENV_VAR = 'foo'

就是这样。

./package.json:

"jest": {
"setupFiles": [
"<rootDir>/jest/setEnvVars.js"
]
}

./jest/setEnvVars.js:

process.env.SOME_VAR = 'value';


在我看来,如果您将环境变量的检索提取到一个实用程序中(如果没有设置环境变量,您可能希望包含一个快速失败的检查),那么您就可以模拟该实用程序,这样会更清晰、更容易理解。

// 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', () => {...});

Serhan C。的回答上展开一点…

根据博客文章如何设置dotenv与笑话测试-深入解释 .,你可以直接在setupFiles中包含"dotenv/config",而不需要创建和引用调用require("dotenv").config()的外部脚本。

也就是说,简单地去做

module.exports = {
setupFiles: ["dotenv/config"]
}

测试文件:

const APP_PORT = process.env.APP_PORT || 8080;

./package.json测试脚本中:

"scripts": {
"test": "jest --setupFiles dotenv/config",
}

./env:

APP_PORT=8080

以@jahller的回答为基础。

我使它具有响应性,所以当事情发生变化时,您不需要保持文件同步。

把它放在你的jest.config.js文件的底部。

const arr = require('fs')
.readFileSync('.env', 'utf8')
.split('\n')
.reduce((vars, i) => {
const [variable, value] = i.split('=')
vars[variable] = value
return vars
}, {})


process.env = Object.assign(process.env, arr)

它读取你的.env文件的内容,拆分每一行并将其缩减为一个对象,然后将其赋值给process.env

只是使用dotenv在jest.setup.js🤷‍♂️

你可以在jest.config.js中导入这个

require('dotenv').config()

这对我很有用

如果你在jest.config.js文件中使用require("dotenv").config(一个没有TypeScript的NodeJS应用程序,如Jialx或Henry Tipantuna所建议的),以上所有方法都有效。

但是如果你在使用ts-jest并且在jest.config.ts文件中。

import dotenv from "dotenv"
dotenv.config()


/* config options below */

当使用Typescript以下作品为我:

< p >根: jest.config.js < / p >

/* eslint-disable @typescript-eslint/no-var-requires */
const { pathsToModuleNameMapper } = require('ts-jest');


const { compilerOptions } = require('./tsconfig.paths.json');


module.exports = {
// [...]
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
};
process.env = Object.assign(process.env, {
env_name: 'dev',
another_var: 'abc123',
});

我有最简单的实现env (specialtest .env)

require("dotenv").config({ path: './test.env' });
const { sum } = require('./sum.js');


describe('sum', () => {


beforeEach(() => {
jest.resetModules(); // remove cache
})


test('should success', () => {
expect(sum(1, 3)).toEqual(4);
})
})


根据@HenryTipantuña的建议,在jest.config.js中导入dotenv,并使用.env。config路径下的Test文件

require('dotenv').config({
path: '.env.test'
})