test process.env mit Jest

101

Ich habe eine App, die von Umgebungsvariablen abhängt wie:

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

und ich möchte das zum Beispiel testen:

  • APP_PORT kann durch die Variable env des Knotens festgelegt werden.
  • oder dass eine expressApp auf dem Port ausgeführt wird, mit dem festgelegt wurdeprocess.env.APP_PORT

Wie kann ich das mit Jest erreichen? Kann ich diese process.envVariablen vor jedem Test festlegen oder sollte ich sie vielleicht irgendwie verspotten?

Tomasz Mularczyk
quelle
Ja, Sie können die Umgebungsvariable setzen
Deep Kakkar
@ Deep AFAIK Ich kann sie nur einmal in der Scherzkonfiguration einstellen.
Tomasz Mularczyk

Antworten:

134

Die Art und Weise, wie ich es getan habe, kann in dieser SO-Frage gefunden werden .

Es ist wichtig, die Module vor jedem Test zurückzusetzen und das Modul dann dynamisch in den Test zu importieren:

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

Wenn Sie nach einer Möglichkeit suchen, env-Werte zu laden, bevor Sie den Jest ausführen, suchen Sie nach der folgenden Antwort . Sie sollten dafür setupFiles verwenden .

Tomasz Mularczyk
quelle
2
Bitte geben Sie die vollständige Antwort
Yves M.
Hat super für mich funktioniert. Wenn Sie einen Standardexport verwenden müssen, können Sie Folgendes tun: const testingModule = require ('../../ config / env'). Default;
Aziz
6
Falls dies bei Ihnen nicht funktioniert, stellen Sie sicher, dass Sie die env-Variable in Ihrem tatsächlichen Code in einer Funktion / einem begrenzten Bereich lesen, anstatt dass globale Variablen auf process.env.YOUR_VARIABLE verweisen.
Penguinsource
1
@learner, wenn ich mich richtig erinnere, delete process.env.NODE_ENV; ist nur ein Überbleibsel aus meinem Code und sollte in Ihrem Fall keine Rolle spielen. Was zählt, ist, dass Sie jest.resetModules()vor dem Test aufrufen und danach das ursprüngliche process.env-Objekt (OLD_ENV) wiederherstellen
Tomasz Mularczyk
1
@MEMark Sie müssen eine Kopie erstellen, um das ursprüngliche Objekt nicht zu mutieren (das Sie später wiederherstellen müssen)
Tomasz Mularczyk
51

Jest's setupFilesist der richtige Weg, um damit umzugehen, und Sie müssen weder ein installieren dotenvnoch ein verwenden.env Datei , damit sie funktioniert.

jest.config.js::

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

.jest/setEnvVars.js::

process.env.MY_CUSTOM_TEST_ENV_VAR = 'foo'

Das ist es.

zgreen
quelle
Dies ist der einfachste Weg, um env-Variablen im Scherz zu behandeln, danke!
klaevv
22

In ./package.json:

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

In ./jest/setEnvVars.js:

process.env.SOME_VAR = 'value';
Emi
quelle
2
Wahrscheinlich der einfachste Weg, den ich gesehen habe. Das dotenv-Paket muss nicht installiert werden.
MattC
21

Sie können die setupFilesFunktion der Scherzkonfiguration verwenden. Wie die Dokumentation sagte ,

Eine Liste von Pfaden zu Modulen, auf denen Code zum Konfigurieren oder Einrichten der Testumgebung ausgeführt wird. Jede setupFile wird einmal pro Testdatei ausgeführt. Da jeder Test in einer eigenen Umgebung ausgeführt wird, werden diese Skripte unmittelbar vor der Ausführung des Testcodes in der Testumgebung ausgeführt.

  1. npm install dotenv dotenv, mit dem auf die env-Variable zugegriffen wird.
  2. Erstellen Sie Ihre .envDatei im Stammverzeichnis Ihrer Anwendung und fügen Sie diese Zeile hinzu.
#.env
APP_PORT=8080
  1. Erstellen Sie Ihre benutzerdefinierte Moduldatei mit dem Namen someModuleForTest.js und fügen Sie diese Zeile hinzu.
//someModuleForTest.js
require("dotenv").config()
  1. Aktualisieren Sie Ihre jest.config.jsDatei wie folgt
module.exports = {
  setupFiles: ["./someModuleForTest"]
}
  1. Sie können in allen Testblöcken auf die Variable von env zugreifen.
test("Some test name", () => {
  expect(process.env.APP_PORT).toBe("8080")
})
Serhan C.
quelle
6

Eine andere Möglichkeit besteht darin, es jest.config.jsnach der module.exportsDefinition zur Datei hinzuzufügen :

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

Auf diese Weise müssen die ENVVariablen nicht in jeder .specDatei definiert werden, und sie können global angepasst werden.

Jahller
quelle
3

Abhängig davon, wie Sie Ihren Code organisieren können, kann eine andere Option darin bestehen, die env-Variable in eine Funktion einzufügen, die zur Laufzeit ausgeführt wird.

In dieser Datei wird die env-Variable zum Zeitpunkt des Imports festgelegt und erfordert dynamische requires, um verschiedene env-Variablen zu testen (wie in dieser Antwort beschrieben ):

const env = process.env.MY_ENV_VAR;

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

export default myModule;

In dieser Datei wird die env var zur envMessageAusführungszeit festgelegt, und Sie sollten in der Lage sein, process.env direkt in Ihren Tests zu mutieren:

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

export default myModule;

Scherztest:

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(...
RobW
quelle
0

Ich denke, Sie könnten das auch versuchen:

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

// test code...

process.env = currentEnv;

Das funktioniert bei mir und Sie brauchen keine Modulsachen

Andy
quelle
Das Problem ist, dass wenn Sie eine andere Datei importieren, die process.env verwendet, eine direkte Änderung keine Auswirkungen hat. Vor jedem Test müssen Sie Jest also Folgendes mitteilen: "Hey, importieren Sie diese Datei und führen Sie sie erneut aus."
Tomasz Mularczyk
0

Meiner Meinung nach ist es viel sauberer und verständlicher, wenn Sie das Abrufen von Umgebungsvariablen in ein Util extrahieren (Sie möchten wahrscheinlich eine Überprüfung einschließen, die schnell fehlschlägt, wenn eine Umgebungsvariable sowieso nicht festgelegt ist), dann können Sie das Util einfach verspotten .

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