test process.env กับ Jest


123

ฉันมีแอปที่ขึ้นอยู่กับตัวแปรด้านสิ่งแวดล้อมเช่น:

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

และฉันต้องการทดสอบตัวอย่างเช่น:

  • APP_PORT สามารถตั้งค่าได้โดยตัวแปร node env
  • หรือexpressแอปที่กำลังทำงานบนพอร์ตที่ตั้งค่าด้วยprocess.env.APP_PORT

ฉันจะบรรลุเป้าหมายนี้ด้วย Jest ได้อย่างไร? ฉันสามารถตั้งค่าprocess.envตัวแปรเหล่านี้ก่อนการทดสอบแต่ละครั้งได้หรือไม่หรือฉันควรล้อเลียนมันบ้าง


ใช่คุณสามารถตั้งค่าตัวแปรสภาพแวดล้อม
Deep Kakkar

@ Deep AFAIK ฉันสามารถตั้งค่าได้เพียงครั้งเดียวใน jest config
Tomasz Mularczyk

คำตอบ:


164

วิธีที่ฉันทำสามารถพบได้ในคำถาม 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
  });
});

ถ้าคุณมองหาวิธีที่จะโหลดค่า env ก่อนที่จะใช้รูปลักษณ์เจ็ทสำหรับคำตอบด้านล่าง คุณควรใช้setupFilesสำหรับสิ่งนั้น


2
โปรดตอบกลับแบบเต็ม
Yves M.

ทำงานได้ดีสำหรับฉัน หากคุณจำเป็นต้องใช้การส่งออกเริ่มต้นคุณสามารถทำได้: const ทดสอบโมดูเล = ต้องใช้ ('../../ config / env') default;
Aziz

8
ในกรณีที่ไม่ได้ผลสำหรับคุณตรวจสอบให้แน่ใจว่าเมื่อคุณอ่านตัวแปร env ในโค้ดจริงของคุณคุณกำลังอ่านในฟังก์ชัน / ขอบเขตที่ จำกัด แทนที่จะมีตัวแปรส่วนกลางที่ชี้ไปที่ process.env.YOUR_VARIABLE
penguinsource

1
@learner ถ้าฉันจำไม่ผิดdelete process.env.NODE_ENV; เป็นเพียงส่วนที่เหลือจากรหัสของฉันและไม่น่าจะสำคัญในกรณีของคุณ สิ่งที่สำคัญคือคุณโทรjest.resetModules()ก่อนการทดสอบและหลังจากนั้นคุณจะกู้คืนกระบวนการเริ่มต้นวัตถุ env (OLD_ENV)
Tomasz Mularczyk

1
@MEMark คุณต้องสร้างสำเนาเพื่อไม่ให้วัตถุต้นฉบับกลายพันธุ์ (ซึ่งคุณต้องกู้คืนในภายหลัง)
Tomasz Mularczyk

70

Jest 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

29

ใน./package.json:

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

ใน./jest/setEnvVars.js:

process.env.SOME_VAR = 'value';


2
อาจเป็นวิธีที่ง่ายที่สุดที่ฉันเคยเห็น ไม่จำเป็นต้องติดตั้งแพ็คเกจ dotenv
MattC

สิ่งนี้ใช้ไม่ได้กับ Create-React-App github.com/facebook/create-react-app/issues/5325สำหรับสิ่งนั้นตัวแปร env ที่จะใช้ในการทดสอบจะต้องเพิ่มในไฟล์. env.test.local
Pere

23

คุณสามารถใช้setupFilesคุณสมบัติของ jest config ตามที่เอกสารกล่าวไว้ว่า

รายการเส้นทางไปยังโมดูลที่รันโค้ดเพื่อกำหนดค่าหรือตั้งค่าสภาพแวดล้อมการทดสอบ ไฟล์ 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")
})

12

อีกทางเลือกหนึ่งคือเพิ่มลงใน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 ถูกตั้งค่าในเวลานำเข้าและต้องใช้ไดนามิกrequireเพื่อทดสอบ 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(...

2

ขยายความอีกเล็กน้อยเกี่ยวกับคำตอบของ 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"]
}

มีเพียงสิ่งนี้เท่านั้นที่ทำงานในด้านของฉัน
fsevenm

0

ฉันคิดว่าคุณสามารถลองสิ่งนี้ได้เช่นกัน:

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

// test code...

process.env = currentEnv;

สิ่งนี้ใช้ได้กับฉันและคุณไม่จำเป็นต้องมีโมดูล


ปัญหาคือถ้าคุณนำเข้าไฟล์อื่นที่ใช้ process.env การเปลี่ยนไฟล์โดยตรงจะไม่มีผลใด ๆ ดังนั้นก่อนการทดสอบแต่ละครั้งคุณต้องบอก Jest ว่า - "เดี๋ยวก่อนนำเข้าและเรียกใช้ไฟล์นี้อีกครั้ง"
Tomasz Mularczyk

0

ในความคิดของฉันมันสะอาดและเข้าใจง่ายกว่ามากถ้าคุณดึงการดึงตัวแปรสภาพแวดล้อมลงในยูทิล (คุณอาจต้องการรวมการตรวจสอบเพื่อล้มเหลวอย่างรวดเร็วหากยังไม่ได้ตั้งค่าตัวแปรสภาพแวดล้อม) จากนั้นคุณสามารถเยาะเย้ย 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', () => {...});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.