test process.env z Jest


123

Mam aplikację, która zależy od zmiennych środowiskowych, takich jak:

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

i chciałbym to przetestować np .:

  • APP_PORT można ustawić za pomocą zmiennej env węzła.
  • lub że expressaplikacja działa na porcie ustawionym zprocess.env.APP_PORT

Jak mogę to osiągnąć dzięki Jest? Czy mogę ustawić te process.envzmienne przed każdym testem, czy może powinienem jakoś z tego kpić?


tak, możesz ustawić zmienną środowiskową
Deep Kakkar

@Deep AFAIK Mogę je ustawić tylko raz w konfiguracji.
Tomasz Mularczyk

Odpowiedzi:


164

Sposób, w jaki to zrobiłem, można znaleźć w tym pytaniu SO .

Ważne jest, aby zresetować moduły przed każdym testem, a następnie dynamicznie zaimportować moduł wewnątrz testu:

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

Jeśli szukasz sposobu na załadowanie wartości env przed uruchomieniem Jest, poszukaj odpowiedzi poniżej . Powinieneś do tego użyć setupFiles .


2
Prosimy o przesłanie pełnej odpowiedzi
Yves M.

U mnie zadziałało świetnie. Jeśli potrzebujesz użyć domyślnego eksportu, możesz to zrobić: const testedModule = require ('../../ config / env'). Default;
Aziz

8
jeśli to nie zadziała, upewnij się, że czytając zmienną env w swoim rzeczywistym kodzie, czytasz ją w funkcji / ograniczonym zakresie, a nie zmienne globalne wskazywane na process.env.YOUR_VARIABLE.
penguinsource

1
@learner, jeśli dobrze pamiętam, delete process.env.NODE_ENV; jest tylko pozostałością z mojego kodu i nie powinno mieć znaczenia w Twoim przypadku. Liczy się to, że dzwonisz jest.resetModules()przed testem, a po nim przywracasz początkowy obiekt process.env (OLD_ENV)
Tomasz Mularczyk

1
@MEMark musisz utworzyć kopię, aby nie mutować oryginalnego obiektu (który później trzeba przywrócić)
Tomasz Mularczyk

70

Jest setupFilesto właściwy sposób radzenia sobie z tym problemem i nie musisz instalować dotenvani .envw ogóle używać pliku, aby działał.

jest.config.js:

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

.jest/setEnvVars.js:

process.env.MY_CUSTOM_TEST_ENV_VAR = 'foo'

Otóż ​​to.


1
To najprostszy sposób radzenia sobie ze zmiennymi env, dzięki!
klaevv

29

W ./package.json:

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

W ./jest/setEnvVars.js:

process.env.SOME_VAR = 'value';


2
Prawdopodobnie najłatwiejszy sposób, jaki widziałem. Nie ma potrzeby instalowania pakietu dotenv.
MattC

to nie zadziała z Create-React-App github.com/facebook/create-react-app/issues/5325 w tym celu zmienne env, które mają być użyte w teście, należy dodać w pliku .env.test.local
Pere

23

Możesz skorzystać z setupFilesfunkcji jest config. Jako dokumentacja mówi , że

Lista ścieżek do modułów, które uruchamiają kod w celu skonfigurowania lub skonfigurowania środowiska testowego. Każdy plik setupFile zostanie uruchomiony raz na plik testowy. Ponieważ każdy test działa we własnym środowisku, skrypty te będą wykonywane w środowisku testowym bezpośrednio przed wykonaniem samego kodu testowego.

  1. npm install dotenv dotenv, który używa do uzyskania dostępu do zmiennej env.
  2. Utwórz .envplik w katalogu głównym aplikacji i dodaj do niego ten wiersz.
#.env
APP_PORT=8080
  1. Utwórz plik modułu niestandardowego pod nazwą someModuleForTest.js i dodaj do niego ten wiersz.
//someModuleForTest.js
require("dotenv").config()
  1. Zaktualizuj swój jest.config.jsplik w ten sposób
module.exports = {
  setupFiles: ["./someModuleForTest"]
}
  1. Możesz uzyskać dostęp do zmiennej env we wszystkich blokach testowych.
test("Some test name", () => {
  expect(process.env.APP_PORT).toBe("8080")
})

12

Inną opcją jest dodanie go do jest.config.jspliku po module.exportsdefinicji:

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

Dzięki temu nie ma potrzeby definiowania ENVzmiennych w każdym .specpliku i można je dostosowywać globalnie.


To fantastyczna odpowiedź. Dziękuję Ci.
spierce7

3

W zależności od tego, jak możesz zorganizować swój kod, inną opcją może być umieszczenie zmiennej env w funkcji wykonywanej w czasie wykonywania.

W tym pliku zmienna env jest ustawiana w czasie importu i wymaga dynamicznych wartości requirew celu przetestowania różnych zmiennych środowiska (zgodnie z opisem w tej odpowiedzi ):

const env = process.env.MY_ENV_VAR;

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

export default myModule;

W tym pliku zmienna env jest ustawiana w envMessageczasie wykonywania i powinieneś być w stanie zmutować process.env bezpośrednio w swoich testach:

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

export default myModule;

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


0

Myślę, że ty też możesz spróbować:

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

// test code...

process.env = currentEnv;

To działa dla mnie i nie potrzebujesz rzeczy modułowych


problem polega na tym, że jeśli zaimportujesz inny plik, który używa process.env, bezpośrednia zmiana nie przyniesie żadnego efektu. Więc przed każdym testem musisz powiedzieć Jest coś w stylu - „hej, zaimportuj i ponownie uruchom ten plik”.
Tomasz Mularczyk

0

Moim zdaniem jest znacznie czystszy i łatwiejszy do zrozumienia, jeśli wyodrębnisz pobieranie zmiennych środowiskowych do narzędzia (prawdopodobnie chcesz dołączyć sprawdzenie, czy szybko się nie powiedzie, jeśli zmienna środowiskowa i tak nie jest ustawiona), wtedy możesz po prostu mockować narzędzie .

// 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', () => {...});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.