데이터베이스 테스트
번역일: 2026년 6월 20일
데이터베이스 테스트
소개
Laravel은 데이터베이스 기반 애플리케이션을 테스트하기 위한 다양한 도구와 어설션을 제공합니다. 모델 팩토리와 시더를 활용하면 Eloquent 모델과 관계를 이용해 테스트용 데이터베이스 레코드를 손쉽게 만들 수 있습니다. 이 문서에서는 이러한 기능들을 하나씩 살펴봅니다.
각 테스트 후 데이터베이스 초기화
테스트를 작성할 때 중요한 점 중 하나는, 이전 테스트에서 삽입된 데이터가 이후 테스트에 영향을 주지 않도록 매 테스트마다 데이터베이스를 깨끗한 상태로 유지하는 것입니다. Laravel이 기본으로 제공하는 Illuminate\Foundation\Testing\RefreshDatabase 트레이트를 사용하면 이 작업을 자동으로 처리할 수 있습니다.
<?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 트레이트는 데이터베이스 스키마가 최신 상태라면 마이그레이션을 새로 실행하지 않습니다. 대신, 각 테스트를 데이터베이스 트랜잭션 안에서 실행한 뒤 롤백합니다. 따라서 이 트레이트를 사용하지 않는 테스트에서 삽입한 레코드는 데이터베이스에 그대로 남아 있을 수 있습니다.
데이터베이스를 완전히 초기화해야 한다면 Illuminate\Foundation\Testing\DatabaseMigrations 또는 Illuminate\Foundation\Testing\DatabaseTruncation 트레이트를 사용할 수 있습니다. 다만, 두 트레이트 모두 RefreshDatabase보다 속도가 상당히 느리므로 꼭 필요한 경우에만 사용하는 것을 권장합니다.
NOTE
세 트레이트의 동작 방식을 간단히 비교하면 다음과 같습니다.
RefreshDatabase— 트랜잭션 롤백 방식. 가장 빠름.DatabaseTruncation— 각 테스트 후 테이블을 TRUNCATE. 중간 속도.DatabaseMigrations— 매 테스트마다 migrate:fresh 실행. 가장 느림.
모델 팩토리
테스트를 실행하기 전에 데이터베이스에 샘플 데이터를 삽입해야 하는 경우가 많습니다. 컬럼 값을 일일이 지정하는 대신, 모델 팩토리를 사용하면 Eloquent 모델의 기본 속성값을 미리 정의해두고 테스트에서 간편하게 재사용할 수 있습니다.
모델 팩토리를 만들고 활용하는 방법은 모델 팩토리 문서에서 자세히 확인할 수 있습니다. 팩토리를 정의했다면 테스트 안에서 다음과 같이 모델을 생성할 수 있습니다.
use App\Models\User;
public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();
// ...
}시더 실행
기능 테스트에서 데이터베이스 시더를 이용해 초기 데이터를 채우고 싶다면 seed 메서드를 호출하면 됩니다. 기본적으로 seed 메서드는 DatabaseSeeder를 실행하며, 이 시더가 다른 모든 시더를 순차적으로 호출합니다. 특정 시더 클래스만 실행하고 싶다면 클래스 이름을 인자로 전달하세요.
<?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,
// ...
]);
}
}매 테스트마다 자동으로 시더를 실행하고 싶다면, 기본 테스트 클래스에 $seed 프로퍼티를 정의하세요. RefreshDatabase 트레이트를 사용하는 테스트가 실행되기 전에 자동으로 시더가 호출됩니다.
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
/**
* 각 테스트 전에 기본 시더를 자동으로 실행할지 여부
*
* @var bool
*/
protected $seed = true;
}$seed가 true이면 Database\Seeders\DatabaseSeeder가 자동으로 실행됩니다. 특정 시더만 실행하고 싶다면 테스트 클래스에 $seeder 프로퍼티를 추가하세요.
use Database\Seeders\OrderStatusSeeder;
/**
* 각 테스트 전에 실행할 특정 시더
*
* @var string
*/
protected $seeder = OrderStatusSeeder::class;사용 가능한 어설션
Laravel은 PHPUnit 기능 테스트에서 사용할 수 있는 다양한 데이터베이스 어설션을 제공합니다. 각 어설션을 아래에서 살펴봅니다.
assertDatabaseCount
데이터베이스의 특정 테이블에 지정한 수만큼의 레코드가 존재하는지 확인합니다.
$this->assertDatabaseCount('users', 5);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);
// 테스트 코드...