Vitest でのテスト実行時に参照させたい環境変数の設定は globalSetup を利用すると便利

2023.09.12

こんにちは、CX事業本部 Delivery部の若槻です。

以前のエントリで、Vitest の Config のtest.envで環境変数を設定する方法を紹介しました。

上記方法によりテストファイルやテスト対象モジュール内で参照させる環境変数を設定することができるのですが、注意点として、globalSetup内では Config で設定した環境変数は参照させることはできず、別途設定が必要という制限がありました。

しかし環境変数の設定処理を複数箇所で行うのは避けたいので色々調べてみたところ、環境変数の設定自体も globalSetup 内で行う方法が良さそうだったので紹介します。

試してみた

globalSetup で環境変数を設定する

次のように globalSetup ファイルで環境変数の設定処理を記述します。同ファイルで定義しているsetupteardownでも環境変数を参照する場合は、その手前に記述するようにします。

globalSetup.ts

interface Env {
  [key: string]: string;
}

export const env: Env = {
  KEY_1: 'DEV_VALUE_1',
  KEY_2: 'DEV_VALUE_2',
  KEY_3: 'DEV_VALUE_3',
};

Object.keys(env).forEach((key) => {
  process.env[key] = env[key];
});

export const setup = (): void => {
  console.log('setup', env.KEY_1);
};

export const teardown = (): void => {
  console.log('teardown', env.KEY_1);
};

Config では、test.globalSetupに上記のファイルパスを指定します。

vite.config.ts

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globalSetup: ['./globalSetup.ts'],
  },
});

動作確認のため、テストファイルおよびテスト対象モジュールでも環境変数を参照します。

src/hoge.ts

const KEY_3 = process.env.KEY_3;

export const hogeFunc = () => {
  console.log('module', KEY_3);
};

src/hoge.test.ts

import { hogeFunc } from './hoge';

import { test, afterAll } from 'vitest';

const KEY_2_VAL = process.env.KEY_2;

afterAll((): void => {
  hogeFunc();
});

test('should pass', (): void => {
  console.log('hogeTest', KEY_2_VAL);
});

テストを実行すると、globalSetup、globalTeardown、テストファイル、テスト対象モジュールのそれぞれで環境変数を参照させることができました。

$ npx vitest run  
setup DEV_VALUE_1

 RUN  v0.34.4 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app

stdout | src/hoge.test.ts > should pass
hogeTest DEV_VALUE_2

stdout | unknown test
module DEV_VALUE_3

 ✓ src/hoge.test.ts (1)
   ✓ should pass

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  01:02:09
   Duration  228ms (transform 26ms, setup 0ms, collect 10ms, tests 1ms, environment 0ms, prepare 47ms)

teardown DEV_VALUE_1

ステージごとに異なる環境変数を設定する

次によくあるパターンとして、development や production などステージごとに異なる環境変数を参照できるようにしてみます。

次のような環境変数を定義するためのファイルを別途作成して、ステージごとの環境変数のオブジェクトを定義します。

environment.ts

interface Env {
  [key: string]: string;
}

export const developmentEnv: Env = {
  KEY_1: 'DEV_VALUE_1',
  KEY_2: 'DEV_VALUE_2',
  KEY_3: 'DEV_VALUE_3',
};

export const productionEnv: Env = {
  KEY_1: 'PRD_VALUE_1',
  KEY_2: 'PRD_VALUE_2',
  KEY_3: 'PRD_VALUE_3',
};

globalSetup で上述のファイルを読み込み、TEST_MODEで指定したステージの環境変数を設定します。

globalSetup.ts

import { developmentEnv, productionEnv } from 'environment';

const TEST_MODE = process.env.TEST_MODE || 'development';

const env = TEST_MODE === 'production' ? productionEnv : developmentEnv;

Object.keys(env).forEach((key) => {
  process.env[key] = env[key];
});

export const setup = (): void => {
  console.log('setup', env.KEY_1);
};

export const teardown = (): void => {
  console.log('teardown', env.KEY_1);
};

npm scripts でそれぞれのステージのTEST_MODEを指定するスクリプトを定義します。

package.json

{
  "scripts": {
    "test:dev": "TEST_MODE=development vitest run",
    "test:prd": "TEST_MODE=production vitest run"
  },
}

それぞれ実行すると、ステージごとに異なる環境変数を参照できることが確認できました。

  • development
$ npm run test:dev

> cdk_sample_app@0.1.0 test:dev
> TEST_MODE=development vitest run

setup DEV_VALUE_1

 RUN  v0.34.4 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app

stdout | src/hoge.test.ts > should pass
hogeTest DEV_VALUE_2

stdout | unknown test
module DEV_VALUE_3

 ✓ src/hoge.test.ts (1)
   ✓ should pass

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  01:05:20
   Duration  242ms (transform 34ms, setup 0ms, collect 11ms, tests 3ms, environment 0ms, prepare 58ms)

teardown DEV_VALUE_1
  • production
$ npm run test:prd

> cdk_sample_app@0.1.0 test:prd
> TEST_MODE=production vitest run

setup PRD_VALUE_1

 RUN  v0.34.4 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app

stdout | src/hoge.test.ts > should pass
hogeTest PRD_VALUE_2

stdout | unknown test
module PRD_VALUE_3

 ✓ src/hoge.test.ts (1)
   ✓ should pass

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  01:06:05
   Duration  246ms (transform 37ms, setup 0ms, collect 9ms, tests 1ms, environment 0ms, prepare 54ms)

teardown PRD_VALUE_1

おわりに

Vitest でのテスト実行時に参照させたい環境変数の設定は globalSetup を利用すると便利だという話でした。

設定処理の重複を避けることができますし、環境変数をオブジェクトで定義するので.envファイルで管理するのに比べて幾分扱いやすくなります。dotenvなどのパッケージを別途導入する必要もありません。

Vitest を利用する上での参考になれば幸いです。

以上