тестовий процес.env з Jest


114

У мене є програма, яка залежить від змінних середовища, таких як:

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

і я хотів би протестувати це, наприклад:

  • APP_PORT можна встановити за допомогою змінної env вузла.
  • або що expressпрограма працює на порту зprocess.env.APP_PORT

Як я можу досягти цього за допомогою Jest? Чи можу я встановити ці process.envзмінні перед кожним тестом, чи я повинен це якось знущатись, можливо?


так, ви можете встановити змінну середовища
Deep Kakkar

@Deep AFAIK Я можу встановити їх лише один раз в конфігурації для жарту.
Томаш Муларчик

Відповіді:


155

Як я це зробив, можна знайти в цьому запитанні SO .

Важливо 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 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
  });
});

Якщо ви шукаєте спосіб завантаження значень env перед запуском Jest, знайдіть відповідь нижче . Для цього слід використовувати setupFiles .


2
Будь ласка, надайте повну відповідь
Ів М.

Відмінно працював для мене. Якщо вам потрібно скористатися експортом за замовчуванням, ви можете зробити: const testModule = require ('../../ config / env'). Default;
Азіз

6
у випадку, якщо це не працює для вас, переконайтесь, що, коли ви читаєте змінну env у своєму фактичному коді, ви читаєте її у функції / обмеженому обсязі, а не маєте глобальні змінні, вказані на process.env.YOUR_VARIABLE.
penguinsource

1
@learner, якщо я правильно пам’ятаю, delete process.env.NODE_ENV; це лише залишки мого коду, і у вашому випадку це не має значення. Важливо те, що ви телефонуєте jest.resetModules()перед тестом, а після нього ви відновлюєте початковий об'єкт process.env (OLD_ENV)
Томаш Муларчик,

1
@MEMark потрібно створити копію, щоб не мутувати вихідний об’єкт (який згодом потрібно відновити)
Томаш Муларчик

60

Жарт - й setupFilesправильний спосіб впоратися з цим, і вам не потрібно встановлювати dotenv, і не використовувати .envфайл на все, щоб зробити його роботу.

jest.config.js:

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

.jest/setEnvVars.js:

process.env.MY_CUSTOM_TEST_ENV_VAR = 'foo'

Це воно.


1
Це найпростіший спосіб обробляти змінні env на жарт, дякую!
klaevv

24

В ./package.json:

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

В ./jest/setEnvVars.js:

process.env.SOME_VAR = 'value';


2
Мабуть, найпростіший спосіб, який я бачив. Не потрібно встановлювати пакет dotenv.
MattC

23

Ви можете скористатися setupFilesфункцією конфигурування жарту. Як свідчить документація ,

Список шляхів до модулів, які запускають певний код для налаштування або налаштування середовища тестування. Кожен файл setupFile запускається один раз для кожного тестового файлу. Оскільки кожен тест працює у своєму власному середовищі, ці сценарії будуть виконуватися в середовищі тестування безпосередньо перед виконанням самого тестового коду.

  1. npm install dotenv dotenv, який використовує для доступу до змінної env.
  2. Створіть .envфайл у кореневому каталозі програми та додайте в нього цей рядок.
#.env
APP_PORT=8080
  1. Створіть власний файл модуля з назвою someModuleForTest.js і додайте в нього цей рядок.
//someModuleForTest.js
require("dotenv").config()
  1. Оновіть jest.config.jsфайл так
module.exports = {
  setupFiles: ["./someModuleForTest"]
}
  1. Ви можете отримати доступ до змінної env у всіх тестових блоках.
test("Some test name", () => {
  expect(process.env.APP_PORT).toBe("8080")
})

10

Інший варіант - додати його до jest.config.jsфайлу після module.exportsвизначення:

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

Таким чином, не потрібно визначати ENVзмінні в кожному .specфайлі, і їх можна регулювати глобально.


Це фантастична відповідь. Дякую.
spierce7

3

Залежно від того, як ви можете впорядкувати свій код, іншим варіантом може бути розміщення змінної env у функції, яка виконується під час виконання.

У цьому файлі env var встановлюється під час імпорту та вимагає динамічних requires для тестування різних env vars (як описано у цій відповіді ):

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;

Тест 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(...

1

Розширюючи трохи відповідь Сергана К. ( https://stackoverflow.com/a/57944454/2708174 ) ...

згідно з цим блогом https://tekloon.dev/using-dotenv-with-jest, ви можете включити його "dotenv/config"безпосередньо setupFiles, без створення та посилання на зовнішній скрипт, який викликає require("dotenv").config().

тобто просто робити

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

0

Я думаю, ви можете спробувати і це:

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

// test code...

process.env = currentEnv;

Це працює для мене, і вам не потрібні модульні речі


проблема полягає в тому, що якщо ви імпортуєте інший файл, який використовує process.env, то його безпосереднє зміна не матиме ефекту. Отже, перед кожним тестом вам потрібно сказати Jest щось на кшталт - "імпортуйте і виконайте цей файл знову".
Томаш Муларчик

0

На мій погляд, це набагато чистіше і простіше зрозуміти, якщо ви витягнете отримання змінних середовища в утиліту (ви, мабуть, хочете включити перевірку на швидкий збій, якщо змінна середовища все одно не встановлена), тоді ви можете просто знущатися над утилітом .

// 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', () => {...});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.