Laravelでデータベースのテストを行う時、RefreshDatabase
やfactory
など便利なメソッドやトレイトが用意されています。
これらを使ってテストを行いますが、Dockerでデータベースコンテナ一つでやると開発で使ってるデータがクリアされてしまってあまりよろしくないです。
今回はテストする時はテスト用のデータベースを使うように設定します。
前提
当記事は上記の記事の補足になる記事です。
Laravel環境構築
$ git clone git@github.com:ucan-lab/docker-laravel.git
$ cd docker-laravel
$ make create-project
環境
- PHP 7.4.4
- Laravel 7.27.0
手順
docker-compose.yml を編集する
$ docker-compose down
※docker-compose.yml
や Dockerfile
を変更する場合は予めコンテナを破棄しておくと良いです。
db-testing:
build: ./infra/docker/mysql
db-testing
サービスの設定を services
配下に追記します。
$ docker-compose up -d
コンテナを作成して起動します。
$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------------------
docker-laravel_app_1 docker-php-entrypoint php-fpm Up 9000/tcp
docker-laravel_db-testing_1 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
docker-laravel_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp
docker-laravel_web_1 nginx -g daemon off; Up 0.0.0.0:80->80/tcp
db-testing
のコンテナが起動していればokです。
.env.testing
$ cp .env.example .env.testing
$ php artisan key:generate --env=testing
DB_CONNECTION=mysql
DB_HOST=db-testing
DB_PORT=3306
DB_DATABASE=laravel_local
DB_USERNAME=phper
DB_PASSWORD=secret
サンプルのテストを作成
$ php artisan make:test SampleTest
tests/Feature/SampleTest.php
ファイルが生成されるので、下記のように書き換えます。
<?php declare(strict_types=1);
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\User;
class SampleTest extends TestCase
{
use RefreshDatabase;
/**
* A basic feature test example.
*
* @return void
*/
public function testExample()
{
factory(User::class)->create(['name' => 'sample']);
$this->assertEquals(1, User::where('name', 'sample')->count());
}
}
テスト実行
$ php artisan test
PASS Tests\Unit\ExampleTest
✓ basic test
PASS Tests\Feature\ExampleTest
✓ basic test
PASS Tests\Feature\SampleTest
✓ example
Tests: 3 passed
Time: 3.74s
テストが通ったことを確認できればokです。
db
データベースのデータも消えていないことを確認してください。
補足: 開発用データベースが消える場合1
テスト用のデータベースコンテナを参照してくれない場合は、設定ファイルがキャッシュされている可能性があります。
$ php artisan config:clear
忘れ防止のため、composerスクリプトに入れるのもいいかもしれません。
{
"scripts": {
"test": [
"@php artisan config:clear",
"@php artisan test"
]
}
}
$ composer test
補足: 開発用データベースが消える場合2
docker-compose.yml
の environment
でサーバー環境変数にデータベースの接続情報等を設定している場合です。
.env.testing
よりもサーバー環境変数が優先されてしまいます。
対策としては、 phpunit.xml
で環境変数を上書きできます。
<php>
<env name="APP_ENV" value="testing" force="true"/>
<env name="DB_CONNECTION" value="mysql" force="true"/>
<env name="DB_HOST" value="db-testing" force="true"/>
<env name="DB_PORT" value="3306" force="true"/>
<env name="DB_DATABASE" value="laravel" force="true"/>
<env name="DB_USERNAME" value="phper" force="true"/>
<env name="DB_PASSWORD" value="secret" force="true"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="MAIL_DRIVER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
</php>
注意としては、 server
タグではなく、 env
タグで指定します。
$_ENV['APP_ENV'] = 'testing'; // env タグ
$_SERVER['APP_ENV'] = 'testing'; // server タグ
参考
- https://phpunit.readthedocs.io/ja/latest/configuration.html
- https://readouble.com/laravel/8.x/ja/testing.html
過去記事
以前に似た記事を書いてました...