Testing Model & Database — Testing

Testing yang Melibatkan Database Saat testing fitur yang berinteraksi dengan database, kita perlu memastikan database dalam kondisi bersih setiap test…

Testing yang Melibatkan Database

Saat testing fitur yang berinteraksi dengan database, kita perlu memastikan database dalam kondisi bersih setiap test. Laravel menyediakan trait RefreshDatabase untuk ini.

RefreshDatabase Trait

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class UserTest extends TestCase
{
    use RefreshDatabase; // Reset database setiap test

    public function test_user_can_be_created(): void
    {
        $user = User::create([
            "name" => "Budi",
            "email" => "[email protected]",
            "password" => bcrypt("password"),
        ]);

        $this->assertDatabaseHas("users", [
            "email" => "[email protected]",
        ]);
    }
}

Model Factories

Factory adalah cara terbaik untuk membuat data test. Tidak perlu mengisi semua kolom secara manual:

// Membuat 1 user dan simpan ke database
$user = User::factory()->create();

// Membuat instance tanpa menyimpan ke database
$user = User::factory()->make();

// Membuat banyak user
$users = User::factory()->count(5)->create();

// Dengan state kustom
$admin = User::factory()->state([
    "role" => "admin",
    "is_active" => true,
])->create();

// Menggunakan named state dari factory
$admin = User::factory()->admin()->create();

Database Assertions

// Cek data ada di database
$this->assertDatabaseHas("users", [
    "name" => "Budi",
    "email" => "[email protected]",
]);

// Cek jumlah record
$this->assertDatabaseCount("users", 5);

// Cek data TIDAK ada di database
$this->assertDatabaseMissing("users", [
    "email" => "[email protected]",
]);

// Cek data soft-deleted
$this->assertSoftDeleted("posts", [
    "id" => $post->id,
]);

Testing Relationships

public function test_user_has_many_posts(): void
{
    $user = User::factory()
        ->has(Post::factory()->count(3))
        ->create();

    $this->assertCount(3, $user->posts);
    $this->assertInstanceOf(Post::class, $user->posts->first());
}

public function test_post_belongs_to_user(): void
{
    $post = Post::factory()
        ->for(User::factory())
        ->create();

    $this->assertInstanceOf(User::class, $post->user);
    $this->assertNotNull($post->user_id);
}

Testing Scopes dan Accessors

public function test_active_scope(): void
{
    User::factory()->count(3)->create(["is_active" => true]);
    User::factory()->count(2)->create(["is_active" => false]);

    $activeUsers = User::active()->get();

    $this->assertCount(3, $activeUsers);
}

public function test_full_name_accessor(): void
{
    $user = User::factory()->create([
        "first_name" => "Budi",
        "last_name" => "Santoso",
    ]);

    $this->assertEquals("Budi Santoso", $user->full_name);
}

Seeding dalam Test

public function test_with_seeded_data(): void
{
    $this->seed(CategorySeeder::class);

    $categories = Category::all();
    $this->assertGreaterThan(0, $categories->count());
}

Test Isolation di Laravel

Test yang saling bocor datanya adalah mimpi buruk — test A lulus, lalu test B gagal karena urutan yang kebetulan. Laravel punya dua trait utama:

TraitYang dilakukanKecepatanKapan pakai
RefreshDatabasePertama: migrate:fresh (hapus semua tabel, migrate ulang). Selanjutnya: bungkus tiap test dalam transaksi lalu rollback.Lambat di test pertama, cepat di test berikutnyaDefault. Pakai saat schema berubah atau saat butuh jaminan DB bersih.
DatabaseTransactionsBungkus tiap test dalam transaksi lalu rollback. Tidak migrate ulang.Paling cepatSaat database sudah di-migrate manual dan tidak berubah.
DatabaseMigrationsJalankan migrate lalu migrate:rollback tiap test.Sangat lambatJarang — hanya untuk test migration itu sendiri.

Jebakan yang Sering Terjadi

Parallel Testing

Laravel punya php artisan test --parallel yang menjalankan test di beberapa proses. Tiap proses butuh database terpisah (testing_1, testing_2, …). Pastikan:

Yang akan kamu pelajari