📝

【Docker】テスト用に用意したDBコンテナがテストで使用されなかった【Laravel】

2023/12/14に公開

概要

Laravelアプリケーションのテスト環境を構築していた際、
テスト中で「テスト用DBコンテナ」が使用されずに「開発用DBコンテナ」が使用されてハマりました。
解消に時間がかかったので忘備録としてまとめます。

結論

  1. Laravelではテスト中に.envではなく.env.testingが使用される
  2. しかしcompose.ymlで環境変数を定義した場合、.envや.env.testingで定義した環境変数よりも優先される
  3. そのため.env.testingでテストDBコンテナを指定しても、docker compose upの際に使用される.envの値がテスト中でも適用される

整理

テストDBの追加

実務で開発が始まったばかりのLaravelアプリケーションではテスト環境が構築されておらず、
私はテストで使用するDBコンテナの追加など環境整備を行っていました。
↓のpostgresが開発で使用するDBとして最初から定義されていたため、postgres-testをテストで使用するDBとして追加しました。

compose.yml
postgres:
    image: postgres:latest
    environment:
      POSTGRES_USER: ${POSTGRES_USERNAME}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

postgres-test:
    image: postgres:latest
    environment:
      POSTGRES_USER: ${POSTGRES_USERNAME}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

テストを実行してみる

コンテナが立ち上がりいざDBを使用したテストを実行したところ、
開発用のDB(postgres)が使用され、テスト用のDB(postgres-test)は使用されていませんでした。

具体的に言うと、

  • 開発用DBにはすでにいくつかデータある
  • テストDBには何もデータが入っていない

にも関わらず、var_dumpで取得したデータを確認すると開発用DBのデータが取得されていました。

テストで使用する環境変数

DBの接続情報はテスト時に使用される.env.testingに以下のように定義していました。

.env.testing
POSTGRES_NAME=test_db
POSTGRES_HOST=postgres-test
POSTGRES_PORT=5432
POSTGRES_USERNAME=root
POSTGRES_PASSWORD=password

POSTGRES_HOSTでテスト時に使用するコンテナ(postgres-test)を指定しています。

.env.testingが使用されているか?

当初.env.testing自体読み込まれていないと思い、環境変数を追加して以下のようなアサーションで確認しました。
しかしテストはpassし.env.testingで定義している環境変数が使用されていることがわかりました。

テスト
$this->assertSame('test-env', env('TEST_ENV'));
.env.testing
TEST_ENV=test-env

DBへの接続情報も確認してみると・・・

同じようにアサーションを使用し、テスト時に使用するコンテナを指定しているPOSTGRES_HOSTを確認しました。
すると「.env.testingで定義されているpostgres-test」ではなく「.envで定義されているpostgres」が取得されていました。

つまり、.env.testingは使用されているのに、DB指定の環境変数のみ.envの値になっていたのです。

色々調べた結果

結論は冒頭に書いた通り、compose.ymlにDB接続の環境変数をenvironmentで定義していたことでした。

compose.yml
php:  // Laravelコンテナ
    environment:
        - POSTGRES_ADDRESS=${POSTGRES_ADDRESS}

こちらのQiitaの記事に以下のような記載がありました。
https://qiita.com/tkek321/items/9c0c5cec1dc349c67f5f

Laravelの .env の内容を書き換えるという手順を省くためサーバー環境変数を設定しています。
ちなみにLaravelの .env よりもサーバー環境変数の値の方が優先されます。

※この記事が参照している記事ではこの文言が削除されているようです。

よってcompose.ymlで定義している場合、テストで.env.testingを使用し開発用のDBではなくテストDBを参照しようとしても無理、ということでした。

laravelコンテナのenvironmentを削除したところテスト用DBを使用するようになりました。

おわりに

いつもお世話になっているucanさんのDocker Laravelリポジトリで「テストDBコンテナを追加するWiki」があるのですが、そこでLaravelコンテナのenvironmentをすべてコメントアウトしている意味がやっと分かりました・・・。
https://github.com/ucan-lab/docker-laravel/wiki/Add-db-testing-Container

GitHubで編集を提案

Discussion