메인 콘텐츠로 건너뛰기

소개

Laravel에는 데이터베이스를 사용하는 기능을 안전하고 빠르게 검증하기 위한 구조가 기본으로 제공됩니다. 데이터베이스 리셋용 트레이트, 모델 팩토리, 시더, 전용 어서션을 조합하면 잘 부러지지 않는 테스트를 작성할 수 있습니다. 먼저 RefreshDatabase를 사용하는 것이 기본입니다. 대부분의 경우 완전 리셋보다 빠르게 테스트의 독립성을 유지할 수 있습니다.

각 테스트 후 데이터베이스 리셋

이전 테스트 데이터가 다음 테스트에 영향을 주지 않도록 Laravel의 데이터베이스 리셋용 트레이트를 이용합니다.
<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('기본 예시', function () {
    $response = $this->get('/');

    $response->assertOk();
});
<?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('/');

        $response->assertOk();
    }
}
RefreshDatabase는 스키마가 최신인지를 판정합니다. 최신이면 트랜잭션으로 테스트를 실행하고, 최신이 아니면 먼저 마이그레이션을 실행합니다. 트랜잭션 방식이 아니라, 매번 완전히 리셋하고 싶은 경우에는 다음 트레이트를 사용합니다.
트레이트동작사용 상황
RefreshDatabase스키마가 최신이면 트랜잭션, 필요할 때만 마이그레이션일반적으로 이것을 첫 번째 후보로 삼는다
DatabaseMigrations각 테스트마다 마이그레이션을 실행매번 마이그레이션 라이프사이클을 거치고 싶은 경우
DatabaseTruncation테이블을 TRUNCATE해서 초기화트랜잭션이 적합하지 않은 환경에서 전체 데이터를 지우고 싶은 경우

모델 팩토리

테스트 전에 데이터를 준비할 때 모델 팩토리를 사용하면 Eloquent 모델을 간결하게 생성할 수 있습니다. 팩토리 정의·state·관계의 자세한 내용은 Eloquent 팩토리를 참조해 주세요.
<?php

use App\Models\User;

test('모델을 생성할 수 있다', function () {
    $user = User::factory()->create();

    expect($user->exists)->toBeTrue();
});
<?php

namespace Tests\Feature;

use App\Models\User;
use Tests\TestCase;

class UserFactoryTest extends TestCase
{
    public function test_models_can_be_instantiated(): void
    {
        $user = User::factory()->create();

        $this->assertTrue($user->exists);
    }
}

시더 실행

테스트 중에 데이터를 투입하고 싶은 경우에는 seed()를 사용합니다. 인수 없이 호출하면 DatabaseSeeder, 인수를 넣으면 특정 시더(또는 배열)를 실행할 수 있습니다.
<?php

use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('주문을 생성할 수 있다', function () {
    $this->seed();

    $this->seed(OrderStatusSeeder::class);

    $this->seed([
        OrderStatusSeeder::class,
        TransactionStatusSeeder::class,
    ]);

    // ...
});
<?php

namespace Tests\Feature;

use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class OrderTest extends TestCase
{
    use RefreshDatabase;

    public function test_orders_can_be_created(): void
    {
        $this->seed();

        $this->seed(OrderStatusSeeder::class);

        $this->seed([
            OrderStatusSeeder::class,
            TransactionStatusSeeder::class,
        ]);

        // ...
    }
}
RefreshDatabase를 사용하는 모든 테스트에서 매번 자동 시드하고 싶은 경우에는 기저 테스트 클래스에 #[Seed] 애트리뷰트를 붙입니다.
<?php

namespace Tests;

use Illuminate\Foundation\Testing\Attributes\Seed;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

#[Seed]
abstract class TestCase extends BaseTestCase
{
}
특정 시더만 자동 실행하고 싶은 경우에는 #[Seeder(...)]를 사용합니다.
<?php

namespace Tests\Feature;

use Database\Seeders\OrderStatusSeeder;
use Illuminate\Foundation\Testing\Attributes\Seeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

#[Seeder(OrderStatusSeeder::class)]
class OrderStatusTest extends TestCase
{
    use RefreshDatabase;
}

사용 가능한 어서션

Laravel에는 Pest / PHPUnit 어느 쪽에서도 사용할 수 있는 데이터베이스 전용 어서션이 준비되어 있습니다.

assertDatabaseCount

테이블 내의 레코드 건수가 기대값과 일치하는지 확인합니다.
$this->assertDatabaseCount('users', 5);
$this->assertDatabaseCount('users', 5);

assertDatabaseEmpty

테이블이 비어 있는지 확인합니다.
$this->assertDatabaseEmpty('users');
$this->assertDatabaseEmpty('users');

assertDatabaseHas

지정한 조건에 일치하는 레코드가 존재하는지 확인합니다.
$this->assertDatabaseHas('users', [
    'email' => '[email protected]',
]);
$this->assertDatabaseHas('users', [
    'email' => '[email protected]',
]);

assertDatabaseMissing

지정한 조건에 일치하는 레코드가 존재하지 않는지 확인합니다.
$this->assertDatabaseMissing('users', [
    'email' => '[email protected]',
]);
$this->assertDatabaseMissing('users', [
    'email' => '[email protected]',
]);

assertSoftDeleted

대상 Eloquent 모델이 소프트 삭제된 상태인지 확인합니다.
$this->assertSoftDeleted($user);
$this->assertSoftDeleted($user);

assertNotSoftDeleted

대상 Eloquent 모델이 소프트 삭제되지 않았는지 확인합니다.
$this->assertNotSoftDeleted($user);
$this->assertNotSoftDeleted($user);

assertModelExists

지정한 모델(또는 모델 컬렉션)이 DB에 존재하는지 확인합니다.
<?php

use App\Models\User;

$user = User::factory()->create();

$this->assertModelExists($user);
<?php

use App\Models\User;

$user = User::factory()->create();

$this->assertModelExists($user);

assertModelMissing

지정한 모델(또는 모델 컬렉션)이 DB에 존재하지 않는지 확인합니다.
<?php

use App\Models\User;

$user = User::factory()->create();
$user->delete();

$this->assertModelMissing($user);
<?php

use App\Models\User;

$user = User::factory()->create();
$user->delete();

$this->assertModelMissing($user);

expectsDatabaseQueryCount

테스트 시작 부분에서 실행되는 데이터베이스 쿼리의 총 개수를 엄격하게 지정합니다. 실제 실행 횟수가 일치하지 않으면 실패합니다.
$this->expectsDatabaseQueryCount(5);

// Test...
$this->expectsDatabaseQueryCount(5);

// Test...
마지막 수정일 2026년 7월 13일