我有一个取决于环境变量的应用程序,例如:
const APP_PORT = process.env.APP_PORT || 8080;
我想测试例如:
- 可以通过节点env变量设置APP_PORT。
- 或某个
express
应用程序正在使用以下命令设置的端口上运行process.env.APP_PORT
我如何用Jest做到这一点?我可以process.env
在每次测试之前设置这些变量,还是应该以某种方式模拟它?
我有一个取决于环境变量的应用程序,例如:
const APP_PORT = process.env.APP_PORT || 8080;
我想测试例如:
express
应用程序正在使用以下命令设置的端口上运行process.env.APP_PORT
我如何用Jest做到这一点?我可以process.env
在每次测试之前设置这些变量,还是应该以某种方式模拟它?
Answers:
我这样做的方式可以在这个SO问题中找到。
在每次测试之前重置模块,然后在测试内部动态导入模块,这一点很重要:
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 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
});
});
如果您在运行Jest之前寻找一种加载env值的方法,请寻找以下答案。您应该为此使用setupFiles。
delete process.env.NODE_ENV;
)只是我代码中的遗留物,对您而言无关紧要。重要的是您需要jest.resetModules()
在测试之前致电,然后在其还原初始process.env对象(OLD_ENV)
笑话setupFiles
是处理此问题的正确方法,您无需安装dotenv
,也无需使用任何.env
文件即可使其工作。
jest.config.js
:
module.exports = {
setupFiles: ["<rootDir>/.jest/setEnvVars.js"]
};
.jest/setEnvVars.js
:
process.env.MY_CUSTOM_TEST_ENV_VAR = 'foo'
而已。
您可以使用setupFiles
笑话配置功能。正如文档所说,
运行一些代码以配置或设置测试环境的模块的路径列表。每个setupFile将对每个测试文件运行一次。由于每个测试都在其自己的环境中运行,因此这些脚本将在执行测试代码本身之前立即在测试环境中执行。
npm install dotenv
用于访问env变量的dotenv。.env
文件创建到应用程序的根目录,并将此行添加到其中。#.env
APP_PORT=8080
//someModuleForTest.js
require("dotenv").config()
jest.config.js
像这样更新文件module.exports = {
setupFiles: ["./someModuleForTest"]
}
test("Some test name", () => {
expect(process.env.APP_PORT).toBe("8080")
})
根据组织代码的方式,另一种选择是将env变量放入运行时执行的函数中。
在此文件中,env var是在导入时设置的,并且需要dynamicrequire
才能测试不同的env var(如本答案所述):
const env = process.env.MY_ENV_VAR;
const envMessage = () => `MY_ENV_VAR is set to ${env}!`;
export default myModule;
在此文件中,env var是在envMessage
执行时设置的,您应该能够直接在测试中对process.env进行突变:
const envMessage = () => {
const env = process.env.MY_VAR;
return `MY_ENV_VAR is set to ${env}!`;
}
export default myModule;
开玩笑的测试:
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(...
扩展Serhan C.的答案(https://stackoverflow.com/a/57944454/2708174)...
根据此博客https://tekloon.dev/using-dotenv-with-jest的介绍,
您可以"dotenv/config"
直接包含在其中setupFiles
,而无需创建和引用调用的外部脚本require("dotenv").config()
。
即,简单地做
module.exports = {
setupFiles: ["dotenv/config"]
}
我认为您也可以尝试以下方法:
const currentEnv = process.env;
process.env = { ENV_NODE: 'whatever' };
// test code...
process.env = currentEnv;
这对我有用,您不需要模块的东西
我认为,如果将对环境变量的提取提取到util中,则它会更清晰,更容易理解(如果您始终未设置环境变量,则可能希望包括检查以快速失败),那么您可以模拟该util 。
// 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', () => {...});