kiểm tra process.env với Jest


115

Tôi có một ứng dụng phụ thuộc vào các biến môi trường như:

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

và tôi muốn kiểm tra điều đó, ví dụ:

  • APP_PORT có thể được đặt bởi biến env của nút.
  • hoặc một expressứng dụng đang chạy trên cổng được đặt vớiprocess.env.APP_PORT

Làm thế nào tôi có thể đạt được điều này với Jest? Tôi có thể đặt các process.envbiến này trước mỗi bài kiểm tra hay tôi nên giả lập nó bằng cách nào đó?


có bạn có thể thiết lập các biến môi trường
Sâu Kakkar

@Deep AFAIK Tôi chỉ có thể đặt chúng một lần trong cấu hình jest.
Tomasz Mularczyk

Câu trả lời:


155

Cách tôi đã làm có thể được tìm thấy trong câu hỏi SO này .

Điều quan trọng là phải đặt lại Mô-đun trước mỗi thử nghiệm và sau đó nhập động mô-đun bên trong thử nghiệm:

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

Nếu bạn đang tìm cách tải các giá trị env trước khi chạy Jest, hãy tìm câu trả lời bên dưới . Bạn nên sử dụng setupFiles cho điều đó.


2
Vui lòng cung cấp câu trả lời đầy đủ
Yves M.

Làm việc rất tốt cho tôi. Nếu bạn cần sử dụng kết xuất mặc định, bạn có thể thực hiện: const testModule = request ('../../ config / env'). Default;
Aziz

6
trong trường hợp điều này không hiệu quả với bạn, hãy đảm bảo rằng khi bạn đang đọc biến env trong mã thực của mình, bạn đang đọc nó trong một hàm / phạm vi giới hạn thay vì có các biến toàn cục được trỏ tới process.env.YOUR_VARIABLE.
penguinsource

1
@learner nếu tôi nhớ không nhầm delete process.env.NODE_ENV; thì chỉ là phần còn lại từ mã của tôi và không thành vấn đề trong trường hợp của bạn. Điều quan trọng là bạn gọi jest.resetModules()trước khi kiểm tra và sau khi kiểm tra, bạn khôi phục đối tượng process.env ban đầu (OLD_ENV)
Tomasz Mularczyk

1
@MEMark bạn cần tạo một bản sao để không làm thay đổi đối tượng ban đầu (sau này bạn cần khôi phục lại)
Tomasz Mularczyk

60

Jest's setupFileslà cách thích hợp để xử lý vấn đề này và bạn không cần cài đặt dotenvhay sử dụng .envtệp nào cả để làm cho nó hoạt động.

jest.config.js:

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

.jest/setEnvVars.js:

process.env.MY_CUSTOM_TEST_ENV_VAR = 'foo'

Đó là nó.


1
Đây là cách đơn giản nhất để xử lý các biến env trong jest, cảm ơn!
klaevv

26

Trong ./package.json:

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

Trong ./jest/setEnvVars.js:

process.env.SOME_VAR = 'value';


2
Có lẽ là cách dễ nhất mà tôi đã thấy. Không cần cài đặt gói dotenv.
MattC

23

Bạn có thể sử dụng setupFilestính năng của jest config. Như tài liệu đã nói rằng,

Danh sách các đường dẫn đến các mô-đun chạy một số mã để cấu hình hoặc thiết lập môi trường thử nghiệm. Mỗi tệp setupFile sẽ được chạy một lần cho mỗi tệp thử nghiệm. Vì mọi thử nghiệm đều chạy trong môi trường riêng của nó, các tập lệnh này sẽ được thực thi trong môi trường thử nghiệm ngay lập tức trước khi tự thực thi mã thử nghiệm.

  1. npm install dotenv dotenv sử dụng để truy cập biến env.
  2. Tạo .envtệp của bạn vào thư mục gốc của ứng dụng và thêm dòng này vào đó.
#.env
APP_PORT=8080
  1. Tạo tệp mô-đun tùy chỉnh của bạn với tên Nó là someModuleForTest.js và thêm dòng này vào đó.
//someModuleForTest.js
require("dotenv").config()
  1. Cập nhật jest.config.jstệp của bạn như thế này
module.exports = {
  setupFiles: ["./someModuleForTest"]
}
  1. Bạn có thể truy cập biến env trong tất cả các khối thử nghiệm.
test("Some test name", () => {
  expect(process.env.APP_PORT).toBe("8080")
})

10

Một tùy chọn khác là thêm nó vào jest.config.jstệp sau module.exportsđịnh nghĩa:

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

Bằng cách này, không cần thiết phải xác định các ENVbiến trong mỗi .spectệp và chúng có thể được điều chỉnh trên toàn cầu.


Đây là một câu trả lời tuyệt vời. Cảm ơn bạn.
spierce7

3

Tùy thuộc vào cách bạn có thể tổ chức mã của mình, một tùy chọn khác có thể là đặt biến env trong một hàm được thực thi trong thời gian chạy.

Trong tệp này, env var được đặt tại thời điểm nhập và yêu cầu các động requiređể kiểm tra các env vars khác nhau (như được mô tả trong câu trả lời này ):

const env = process.env.MY_ENV_VAR;

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

export default myModule;

Trong tệp này, env var được đặt tại envMessagethời điểm thực thi và bạn có thể thay đổi process.env trực tiếp trong các thử nghiệm của mình:

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

export default myModule;

Thử nghiệm 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

Tôi nghĩ bạn cũng có thể thử điều này:

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

// test code...

process.env = currentEnv;

Điều này phù hợp với tôi và bạn không cần những thứ mô-đun


vấn đề là nếu bạn nhập một tệp khác sử dụng process.env thì việc thay đổi trực tiếp nó sẽ không có hiệu lực. Vì vậy, trước mỗi lần kiểm tra, bạn cần nói với Jest những điều như - "hey import và thực thi lại tệp này".
Tomasz Mularczyk

0

Theo ý kiến ​​của tôi, sẽ rõ ràng và dễ hiểu hơn nhiều nếu bạn trích xuất việc truy xuất các biến môi trường vào một tiện ích (có thể bạn muốn bao gồm một kiểm tra để thất bại nhanh chóng nếu một biến môi trường không được thiết lập), sau đó bạn có thể giả lập sử dụng .

// 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', () => {...});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.