node.jsでprocess.envをスタブする方法は?


81

でスタブprocess.env.FOOしたいbar

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

よくわかりません。文書を読みましたが、まだわかりません。sinonjsドキュメント

sinonjsは一例であり、sinonjsは問題ありません。


環境変数をスタブ化する理由を説明できますか?これをUNIXライクなOSまたはWindowsで行っていますか?
slebetman 2014

1
@slebetman依存するサービスのAPIキーなど、構成には環境変数に依存するのが一般的です。12factor.netを参照してください。
Andrew Homeyer 2015

1
@AndrewHomeyer:はい、しかしあなたはそれらをスタブしません-あなたはそれらをテストのために正しく設定しました
slebetman 2015

回答:


74

私の理解ではprocess.env、プロパティを設定するときに、他の変数と同じように扱うことができます。ただし、のすべての値はprocess.env文字列でなければならないことに注意してください。したがって、テストで特定の値が必要な場合:

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

状態が他のテストに漏れないようにするには、変数を元の値にリセットするか、完全に削除してください。

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

8
わたしにはできる。覚えておくべきことの1つは、モジュールが最初にロードされるときにNODE_ENVを読み取るモジュールをテストする場合、モジュールをロードする前にNODE_ENVを設定することをお勧めします(つまり、NODE_ENVはbeforeEachブロックで設定できます)。 、しかしそれは前に私をつまずかせました。
テレンス

問題が発生した場合は、誰かが見られるようにコードスニペットを投稿できますか?私はMochaテストランナーの構文を念頭に置いて答えを書きましたが、他のランナー(ラボなど)でも機能するはずです。
Joshua Dutton 2017年

2
これは機能しますが、を使用すると癖が見つかりましたjest。私の製品コードでは、envからconstに割り当てました(例const X = process.env.X)。constは、関数スコープではなく、(ES)モジュールスコープで宣言されました。私のテストはjest --watch、再試行されたテスト実行では常に合格しましたが、最初の実行では常に失敗しました。ここで完全には理解していない注文の問題があります。常にprocess.env本番コード(つまり関数)から直接読み取っていて、モジュールレベルでキャッシュしていないことを確認してください。
ジェシーブキャナン

1
これは、関数でprocess.envを評価している場合はうまく機能しますが、定数の場合はうまく機能しません。たとえば、const myValue = process.env.value ? process.env.value : 'default'テスト内でprocess.env.valueを設定すると、機能しませんでした。ただし、const myValue = () => (process.env.value ? process.env.value : 'default')は期待どおりに機能します。
ラファエルマルケス

この同じ静脈では、私が持っていた:const SWITCH_ON = (process.env.SWITCH_ON.toLowerCase() === 'true');私は2つのラインにそれを変更して動作しませんでした:var switchOn = process.env.SWITCH_ON; const SWITCH_ON = (switchOn === undefined ? false : switchOn.toLowerCase() === 'true');初期は私に与え続けundefined、私がやっていたエラー.toLowerCase()
Scalaの熱狂的ファンを

25

process.envユニットテストでは、クローンを作成し、ティアダウンメソッドで復元することで、適切にスタブ化することができました。

モカの使用例

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

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

...

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

これは、process.envがテストしている関数でのみ読み取られている場合にのみ機能することに注意してください。たとえば、テストしているコードが変数を読み取り、それをクロージャーで使用する場合、それは機能しません。あなたはおそらくそれを適切にテストするためにキャッシュされたrequireを無効にします。

たとえば、次の場合、envはスタブされません。

const nodeEnv = process.env.NODE_ENV;

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

3
このプロセスはほとんど機能しました。「after」メソッドを微調整する必要がありました。after(() => { process.env = Object.assign({}, env); }); それ以外の場合、テストは共有コピーを操作します。各テストの後に新しいバージョンを設定する必要があります。
カイル

1
@カイル..いいえ、そうではありませんか?ファイルの先頭でenvを一度設定すると、テストスイートの最初の状態に復元されます
Prisoner

4

spec-helper.coffeeまたはあなたのsinonサンドボックスを設定似たような、オリジナルのキープトラックprocess.envとあなたがテストの間に漏れないと毎回リセットするために覚えておく必要はありませんので、各テストの後にそれを復元します。

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

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

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

テストではprocess.env、通常どおりに使用します。

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

underscoreclone関数はの代わりに機能しcloneDeepます-underscoreではなくをすでに使用している場合に便利ですlodash
ロブ

4

sinonを使用すると、このような変数をスタブ化できます。

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

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

 myObj.example; // 'newValue'

この例は、フォームシノンのドキュメントです。https://sinonjs.org/releases/v6.1.5/stubs/


その知識があれば、任意の環境変数をスタブ化できます。あなたの場合、それは次のようになります:

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

5
「存在しない独自のプロパティFOOをスタブできません」というエラーが表示されました。また、私のテストを実行するためにwallaby.jsを使用しています。
WillLovett19年

1
「env変数のスタブはどのように見えますか?」という質問への回答を投稿していただきありがとうございます。だけではなく、我々はそれらを手動で操作することができますので、我々はする必要はありません:)というのが
ウィル

@WillLovettと同じエラーが発生し、ユニットテストスクリプトの上部にrequire呼び出しを追加することで解決 require('dotenv').config();しました。これは通常、アプリケーションの実行時に呼び出されることに気付きましたが、ユニットテストを直接実行している場合は、 requireステートメントが欠落します。
フォンピットマン

4

ユニットテスト中にprocess.envをすばやくモックする方法。

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

しかし、テスト前にprocess.envに存在しなかった可能性のあるプロパティについてはどうでしょうか。次のパッケージを使用すると、存在しない環境変数をテストできます。

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


process.env.USERまだ値がない場合、これは機能しません。
SohailSi20年

0

process.envに存在しないキーをスタブ化する場合は、これを使用できます。

const sinon = require('sinon')
let sandbox = sinon.createSandbox();
sandbox.stub(process, 'env').value({ 'SOME_KEY': 'SOME_VALUE' });
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.