Làm thế nào để khai thác process.env trong node.js?


81

Tôi muốn khai process.env.FOOvới bar.

var sinon = require('sinon');
var stub = sinon.stub(process.env, 'FOO', 'bar');

Tôi bối rối. Tôi đọc tài liệu, nhưng tôi vẫn chưa hiểu. tài liệu sinonjs

sinonjs là một ví dụ, không phải sinonjs là được.


Bạn có thể giải thích lý do tại sao bạn muốn khai thác môi trường không? Bạn đang thực hiện việc này trên hệ điều hành giống như Unix hoặc Windows?
slbetman

1
@slebetman thường dựa vào các biến môi trường để cấu hình, chẳng hạn như khóa API cho một dịch vụ mà bạn dựa vào. Xem 12factor.net .
Andrew Homeyer,

1
@AndrewHomeyer: Vâng, nhưng bạn không còn sơ khai họ - hãy để họ ra một cách chính xác cho kỳ thi này
slebetman

Câu trả lời:


74

Theo hiểu biết của tôi process.env, bạn có thể đơn giản coi nó như bất kỳ biến nào khác khi thiết lập các thuộc tính của nó. Tuy nhiên, hãy nhớ rằng mọi giá trị trong process.envphải là một chuỗi. Vì vậy, nếu bạn cần một giá trị cụ thể trong thử nghiệm của mình:

   it('does something interesting', () => {
      process.env.NODE_ENV = 'test';
      // ...
   });

Để tránh rò rỉ trạng thái sang các thử nghiệm khác, hãy đảm bảo đặt lại biến về giá trị ban đầu hoặc xóa hoàn toàn:

   afterEach(() => {
       delete process.env.NODE_ENV;
   });

8
Nó làm việc cho tôi. Một điều cần lưu ý là nếu bạn đang thử nghiệm một mô-đun đọc NODE_ENV khi mô-đun này tải lần đầu tiên, có thể bạn sẽ muốn đặt NODE_ENV trước khi tải mô-đun (nghĩa là NODE_ENV có thể được đặt trong một khối beforeEach.) Điều này có vẻ hiển nhiên , nhưng nó đã khiến tôi vấp ngã trước đây.
Terrence

Nếu bạn đang gặp sự cố, bạn có thể đăng đoạn mã để ai đó xem không? Tôi đã viết câu trả lời của mình với cú pháp của trình chạy thử nghiệm Mocha, nhưng nó cũng sẽ hoạt động với bất kỳ trình chạy nào khác (ví dụ như phòng thí nghiệm).
Joshua Dutton

2
Điều này hoạt động, nhưng tôi tìm thấy một điểm không ổn khi sử dụng jest. Trong mã sản xuất của mình, tôi đã gán từ env thành const (ví dụ const X = process.env.X). Hằng số được khai báo ở phạm vi mô-đun (ES), không phải phạm vi chức năng. Các bài kiểm tra của tôi luôn vượt qua khi jest --watchchạy thử lại, nhưng luôn thất bại trong lần chạy đầu tiên. Có một vấn đề đặt hàng mà tôi không hiểu hết ở đây. Chỉ cần đảm bảo rằng bạn luôn đọc trực tiếp từ process.envmã sản xuất của mình (tức là trong một hàm) và không lưu vào bộ nhớ đệm ở cấp mô-đun.
Jesse Buchanan,

1
điều này hoạt động tốt nếu bạn đang đánh giá process.env trong một hàm, nhưng không hoạt động nếu nó là một hằng số. ví dụ, tôi const myValue = process.env.value ? process.env.value : 'default'sẽ không hoạt động nếu bạn đặt giá trị process.env. bên trong một bài kiểm tra. Tuy nhiên, const myValue = () => (process.env.value ? process.env.value : 'default') hoạt động như mong đợi!
Rafael Marques

Cũng theo cách này, tôi có: dòng const SWITCH_ON = (process.env.SWITCH_ON.toLowerCase() === 'true');này không hoạt động nên tôi đã thay đổi nó thành hai dòng: var switchOn = process.env.SWITCH_ON; const SWITCH_ON = (switchOn === undefined ? false : switchOn.toLowerCase() === 'true');Dòng đầu tiên liên tục cho tôi undefinedlỗi ở nơi tôi đang làm.toLowerCase()
Scala E say mê

25

Tôi đã có thể được process.envkhai thác đúng cách trong các bài kiểm tra đơn vị của mình bằng cách sao chép nó và trong một phương pháp xé nhỏ khôi phục nó.

Ví dụ sử dụng Mocha

const env = Object.assign({}, process.env);

after(() => {
    process.env = env;
});

...

it('my test', ()=> {
    process.env.NODE_ENV = 'blah'
})

Hãy nhớ rằng điều này sẽ chỉ hoạt động nếu process.env chỉ được đọc trong chức năng bạn đang thử nghiệm. Ví dụ: nếu mã mà bạn đang kiểm tra đọc biến và sử dụng nó trong một lần đóng, nó sẽ không hoạt động. Bạn có thể làm mất hiệu lực yêu cầu đã lưu trong bộ nhớ cache để kiểm tra điều đó đúng cách.

Ví dụ: phần sau sẽ không có env khai thác:

const nodeEnv = process.env.NODE_ENV;

const fnToTest = () => {
   nodeEnv ...
}

3
Quá trình này hầu hết đã hoạt động. Tôi đã phải điều chỉnh phương thức "sau khi". after(() => { process.env = Object.assign({}, env); }); Nếu không, các bài kiểm tra sẽ thao túng bản sao được chia sẻ. Cần đặt sau mỗi lần kiểm tra một phiên bản mới.
Kyle

1
@Kyle .. không nó sẽ không? giả sử bạn thiết lập env một lần ở đầu tệp của mình, nó sẽ được khôi phục về những gì ở đầu bộ thử nghiệm của bạn ..
Prisoner

4

Trong một spec-helper.coffeehoặc một cái gì đó tương tự nơi bạn thiết lập hộp cát sinon của mình, hãy theo dõi bản gốc process.envvà khôi phục nó sau mỗi lần kiểm tra, để bạn không bị rò rỉ giữa các lần kiểm tra và không phải nhớ đặt lại mỗi lần.

_ = require 'lodash'
sinon = require 'sinon'

beforeEach ->
    @originalProcessEnv = _.cloneDeep process.env

afterEach ->
    process.env = _.cloneDeep @originalProcessEnv

Trong thử nghiệm của bạn, hãy sử dụng process.envnhư bình thường.

it 'does something based on an env var', ->
    process.env.FOO = 'bar'

underscore's clonechức năng làm việc ở vị trí của cloneDeep- hữu ích nếu bạn đã sử dụng underscorehơn lodash.
Rob

4

Với sinon, bạn có thể khai thác bất kỳ biến nào như thế này.

 const myObj = {
    example: 'oldValue', 
 };

 sinon.stub(myObj, 'example').value('newValue');

 myObj.example; // 'newValue'

Ví dụ này là tài liệu dạng sinon. https://sinonjs.org/releases/v6.1.5/stubs/


Với kiến ​​thức đó, bạn có thể khai thác bất kỳ biến môi trường nào. Trong trường hợp của bạn, nó sẽ như thế này:

 let stub = sinon.stub(process.env, 'FOO').value('bar');

5
Tôi nhận được lỗi "Không thể kê khai thuộc tính riêng không tồn tại FOO". Cũng sử dụng wallaby.js để chạy thử nghiệm của tôi.
Will Lovett

1
Cảm ơn bạn đã đăng câu trả lời cho câu hỏi "Việc khai thác một env var trông như thế nào?" thay vì chỉ nói rằng chúng tôi không cần vì chúng tôi có thể thao tác chúng theo cách thủ công :)
Sẽ

Tôi đã gặp lỗi tương tự như @WillLovett và đã giải quyết nó bằng cách thêm lệnh gọi yêu cầu gần đầu tập lệnh kiểm tra đơn vị của mình: require('dotenv').config();Tôi nhận ra rằng điều này thường được gọi khi ứng dụng của tôi chạy, nhưng nếu tôi đang chạy trực tiếp kiểm tra đơn vị của mình, điều này tuyên bố yêu cầu sẽ bị thiếu.
Von Pittman

4

Cách mô phỏng nhanh process.env trong quá trình thử nghiệm đơn vị.

https://glebbahmutov.com/blog/mocking-process-env/

const sinon = require('sinon')
let sandbox = sinon.createSandbox()

beforeEach(() => {
  sandbox.stub(process.env, 'USER').value('test-user')
})

it('has expected user', () => {
  assert(process.env.USER === 'test-user', 'wrong user')
})

afterEach(() => {
  sandbox.restore()
})

Nhưng còn các thuộc tính có thể không tồn tại trong process.env trước khi kiểm tra thì sao? Bạn có thể sử dụng gói sau và sau đó bạn sẽ có thể kiểm tra các biến env không tồn tại.

https://github.com/bahmutov/mocked-env


Điều này sẽ không hoạt động khi process.env.USERchưa có giá trị.
Sohail Si
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.