본문 바로가기

데이터베이스 테스트

번역일: 2026년 6월 20일

데이터베이스 테스트

소개

Laravel은 데이터베이스 기반 애플리케이션을 테스트할 때 유용한 다양한 도구와 어설션을 제공합니다. 모델 팩토리와 시더를 활용하면 Eloquent 모델과 관계를 이용해 테스트용 데이터베이스 레코드를 손쉽게 생성할 수 있습니다. 이 문서에서는 이러한 기능들을 차례로 살펴봅니다.

각 테스트 후 데이터베이스 초기화

테스트를 작성할 때 가장 먼저 고민해야 할 것은 테스트 간 데이터 격리입니다. 이전 테스트에서 삽입한 데이터가 다음 테스트에 영향을 주지 않도록, Laravel이 기본으로 제공하는 Illuminate\Foundation\Testing\RefreshDatabase 트레이트를 사용하세요. 테스트 클래스에 이 트레이트를 추가하기만 하면 됩니다.

Pest

<?php use Illuminate\Foundation\Testing\RefreshDatabase; uses(RefreshDatabase::class); test('기본 예제', function () { $response = $this->get('/'); // ... });

PHPUnit

<?php namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ExampleTest extends TestCase { use RefreshDatabase; /** * 기본 기능 테스트 예제 */ public function test_basic_example(): void { $response = $this->get('/'); // ... } }

RefreshDatabase 트레이트는 데이터베이스 스키마가 최신 상태라면 마이그레이션을 다시 실행하지 않습니다. 대신 각 테스트를 데이터베이스 트랜잭션 안에서 실행한 뒤 롤백하는 방식으로 데이터를 초기화합니다. 따라서 이 트레이트를 사용하지 않는 테스트 케이스에서 삽입한 레코드는 데이터베이스에 그대로 남아 있을 수 있습니다.

NOTE

데이터베이스를 완전히 초기화하고 싶다면 Illuminate\Foundation\Testing\DatabaseMigrations 또는 Illuminate\Foundation\Testing\DatabaseTruncation 트레이트를 사용할 수 있습니다. 단, 두 방식 모두 RefreshDatabase에 비해 속도가 상당히 느립니다.

모델 팩토리

테스트를 실행하기 전에 데이터베이스에 샘플 레코드를 넣어야 할 때가 많습니다. 컬럼 값을 일일이 지정하는 대신, 모델 팩토리를 사용하면 Eloquent 모델별로 기본 속성값을 정의해두고 테스트마다 간편하게 재사용할 수 있습니다.

모델 팩토리를 정의하고 활용하는 방법은 모델 팩토리 문서를 참고하세요. 팩토리를 정의했다면 테스트 내에서 다음과 같이 모델을 생성할 수 있습니다.

Pest

use App\Models\User; test('모델 인스턴스를 생성할 수 있다', function () { $user = User::factory()->create(); // ... });

PHPUnit

use App\Models\User; public function test_models_can_be_instantiated(): void { $user = User::factory()->create(); // ... }

시더 실행

기능 테스트 중에 데이터베이스 시더로 초기 데이터를 채우고 싶다면 seed 메서드를 호출하세요. 기본적으로 seed 메서드는 DatabaseSeeder를 실행하며, 이 안에서 다른 모든 시더가 순차적으로 실행됩니다. 특정 시더 클래스만 실행하려면 클래스명을 인수로 전달하면 됩니다.

Pest

<?php use Database\Seeders\OrderStatusSeeder; use Database\Seeders\TransactionStatusSeeder; use Illuminate\Foundation\Testing\RefreshDatabase; uses(RefreshDatabase::class); test('주문을 생성할 수 있다', function () { // DatabaseSeeder 전체 실행 $this->seed(); // 특정 시더만 실행 $this->seed(OrderStatusSeeder::class); // ... // 여러 시더를 배열로 지정해 실행 $this->seed([ OrderStatusSeeder::class, TransactionStatusSeeder::class, // ... ]); });

PHPUnit

<?php namespace Tests\Feature; use Database\Seeders\OrderStatusSeeder; use Database\Seeders\TransactionStatusSeeder; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ExampleTest extends TestCase { use RefreshDatabase; /** * 새 주문 생성 테스트 */ public function test_orders_can_be_created(): void { // DatabaseSeeder 전체 실행 $this->seed(); // 특정 시더만 실행 $this->seed(OrderStatusSeeder::class); // ... // 여러 시더를 배열로 지정해 실행 $this->seed([ OrderStatusSeeder::class, TransactionStatusSeeder::class, // ... ]); } }

RefreshDatabase 트레이트를 사용하는 모든 테스트 전에 자동으로 시더를 실행하고 싶다면, 기본 테스트 클래스에 $seed 속성을 정의하면 됩니다.

<?php namespace Tests; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { /** * 각 테스트 전에 기본 시더를 자동 실행할지 여부 * * @var bool */ protected $seed = true; }

$seedtrue이면, RefreshDatabase 트레이트를 사용하는 테스트가 실행될 때마다 Database\Seeders\DatabaseSeeder가 자동으로 실행됩니다. 특정 시더만 실행하고 싶다면 테스트 클래스에 $seeder 속성을 추가하세요.

use Database\Seeders\OrderStatusSeeder; /** * 각 테스트 전에 실행할 특정 시더 * * @var string */ protected $seeder = OrderStatusSeeder::class;

사용 가능한 어설션

Laravel은 PestPHPUnit 기능 테스트에서 사용할 수 있는 다양한 데이터베이스 어설션을 제공합니다. 각 어설션을 아래에서 설명합니다.

assertDatabaseCount

테이블에 지정한 수만큼의 레코드가 존재하는지 확인합니다.

$this->assertDatabaseCount('users', 5);

assertDatabaseEmpty

테이블에 레코드가 하나도 없는지 확인합니다.

$this->assertDatabaseEmpty('users');

assertDatabaseHas

테이블에 주어진 키/값 조건에 일치하는 레코드가 존재하는지 확인합니다.

$this->assertDatabaseHas('users', [ 'email' => 'sally@example.com', ]);

assertDatabaseMissing

테이블에 주어진 키/값 조건에 일치하는 레코드가 존재하지 않는지 확인합니다.

$this->assertDatabaseMissing('users', [ 'email' => 'sally@example.com', ]);

assertSoftDeleted

주어진 Eloquent 모델이 소프트 삭제(soft delete) 상태인지 확인합니다.

$this->assertSoftDeleted($user);

assertNotSoftDeleted

주어진 Eloquent 모델이 소프트 삭제되지 않은 상태인지 확인합니다.

$this->assertNotSoftDeleted($user);

assertModelExists

주어진 모델 인스턴스가 데이터베이스에 존재하는지 확인합니다.

use App\Models\User; $user = User::factory()->create(); $this->assertModelExists($user);

assertModelMissing

주어진 모델 인스턴스가 데이터베이스에 존재하지 않는지 확인합니다.

use App\Models\User; $user = User::factory()->create(); $user->delete(); $this->assertModelMissing($user);

expectsDatabaseQueryCount

테스트 시작 시점에 호출하면, 해당 테스트에서 실행될 것으로 예상되는 데이터베이스 쿼리 수를 지정할 수 있습니다. 실제 실행된 쿼리 수가 이 값과 다를 경우 테스트가 실패합니다. N+1 쿼리 문제처럼 예기치 않은 쿼리 증가를 조기에 발견하는 데 유용합니다.

$this->expectsDatabaseQueryCount(5); // 테스트 코드...

이 문서는 Laravel 공식 문서(MIT)를 한국 개발자를 위해 번역·재구성한 것입니다.

번역일: 2026년 6월 20일