Test yang baik pendek, eksplisit, dan memakai assertion bawaan framework — bukan assertTrue untuk segalanya. Laravel menyediakan ratusan assertion berbasis nama-natural persis untuk itu: dibaca seperti kalimat (assertRedirect, assertDatabaseHas), sehingga test tetap dimengerti enam bulan kemudian tanpa membuka implementasinya. Chapter ini merangkum yang paling sering dibutuhkan per kelompok: assertion HTTP, assertion database, fake untuk layanan eksternal, dan helper waktu. Dasar teorinya sudah dibahas di Konsep Testing
; kartu ini dirancang untuk dibuka persis saat sedang menulis test.
Satu kenyamanan yang membuat assertion HTTP terasa lancar: semuanya berantai pada objek response. Kode $response->assertStatus(200)->assertSee('Berhasil') mengeksekusi dua pemeriksaan pada satu objek yang sama, dan kegagalan pertama langsung menghentikan test dengan pesan yang menyebut persis assertion mana yang gugur. Perilaku berantai inilah yang membuat test Laravel terasa seperti menulis daftar harapan, bukan prosedur ritual.
Assertion HTTP #
| Assertion | Memeriksa | Kapan dipakai |
|---|---|---|
assertStatus(200) | Kode status persis | kasus umum |
assertOk() / assertCreated() / assertNoContent() | 200 / 201 / 204 ringkas | endpoint API |
assertNotFound() / assertForbidden() / assertUnauthorized() | 404 / 403 / 401 | halaman terproteksi |
assertRedirect('/login') | Status 3xx + Location | form berhasil → redirect |
assertSee('Berhasil') | String ada di body HTML | cek konten halaman |
assertSeeInOrder([...]) | Kemunculan berurutan | urutan daftar |
assertDontSee('error') | String tidak ada | — |
assertViewHas('tugas') | Data yang dikirim ke view | controller + view |
assertSessionHas('status') | Flash session terpasang | pola PRG |
assertSessionHasErrors('judul') | Error validasi tersimpan | form invalid |
assertCookie('ingat') / assertHeader(...) | Cookie / header response | keamanan |
Dengan berpindah ke endpoint JSON, keluarga assertJson* mengambil alih: assertJson(['data' => [...]]) untuk struktur, assertJsonPath('data.0.judul', 'Belajar Laravel') untuk satu nilai, assertJsonCount(3, 'data') untuk jumlah item, dan assertJsonStructure(['data' => ['*' => ['id', 'judul']]]) untuk bentuk tanpa nilai — semuanya dibahas di HTTP Tests
dan API Testing
.
Assertion Database #
| Assertion | Memeriksa |
|---|---|
assertDatabaseHas('tugas', ['judul' => 'Belajar Laravel']) | Baris cocok ada |
assertDatabaseMissing('tugas', [...]) | Baris cocok tidak ada |
assertDatabaseCount('tugas', 3) | Jumlah baris persis |
assertModelExists($tugas) | Model benar-benar tersimpan |
assertModelMissing($tugas) | Model sudah terhapus |
assertSoftDeleted($tugas) | Model soft-deleted |
Assertion ini bekerja langsung ke database apa pun drivernya, menjadikannya jembatan antara test HTTP dan data — pola lengkapnya di Database Testing
. Aturan praktis pemilihannya: gunakan assertDatabaseHas saat test tidak peduli modelnya (misal memverifikasi baris pivot atau data lewat query builder), dan gunakan assertModelExists saat objek model sedang kita pegang — keduanya membaca tabel yang sama, beda hanya kenyamanan argumennya.
Inventaris Fake #
Fake mengganti layanan eksternal dengan peniru in-memory supaya test cepat dan deterministik.
| Fake | Pasang | Assertion utama |
|---|---|---|
Mail::fake() | Mail::assertSent(Mailable::class) | assertQueued, assertNotSent, assertSentTimes, assertNothingSent |
Notification::fake() | Notification::assertSentTo($user, Nama::class) | assertNotSentTo, assertSentToTimes, assertNothingSentTo |
Queue::fake() | Queue::assertPushed(Job::class) | assertPushedOn('nama-queue', ...), assertNotPushed |
Event::fake() | Event::assertDispatched(Event::class) | assertNotDispatched, assertDispatchedTimes |
Bus::fake() | Bus::assertDispatched(Command::class) | assertBatched, assertNotDispatched |
Storage::fake('foto') | Storage::disk('foto')->assertExists($path) | assertMissing, assertCount, assertDirectoryEmpty |
Http::fake() | Http::assertSent(fn ($r) => $r->url() === ...) | assertNotSent, assertNothingSent |
Untuk Storage::fake(), assertion berjalan pada disk tiruan itu sehingga file tidak pernah menyentuh disk sungguhan. Kombinasi fake dan job dibedah di Queue dan Event Testing
, sedangkan tipologi lengkapnya di Mocking dan Fakes
.
Helper Waktu dan Trait #
Dua helper membuat test waktu jadi deterministik. travelTo() (atau travel(5)->minutes()) membekukan jam aplikasi sehingga logika terjadwal bisa diuji tanpa menunggu, sedangkan actingAs($user) membuat request test seolah-olah datang dari user yang sedang login — pola standar di Authentication Testing
.
Untuk isolasi database, tiga trait berbagi tugas yang sama dengan strategi berbeda. Pilihan default kami adalah RefreshDatabase: migrasi hanya dijalankan sekali per proses test, lalu tiap test dibungkus transaksi yang dibatalkan di akhir — cepat dan aman sekaligus. Dua trait lainnya ada untuk kasus tepi: DatabaseMigrations paling bersih namun paling lambat karena migrasi ulang tiap test, sedangkan DatabaseTruncations unggul saat test melewati proses Schema berat atau berjalan paralel.
| Trait | Strategi reset |
|---|---|
RefreshDatabase | Migrasi sekali lalu transaksi per test — default terbaik |
DatabaseMigrations | Migrasi ulang penuh tiap test — lambat, paling bersih |
DatabaseTruncations | Truncate tabel tiap test — cepat untuk ratusan test |
Sebagai bukti bahwa kartu ini bekerja, berikut test mini yang memakai actingAs, RefreshDatabase, assertStatus, dan assertDatabaseHas — persis seperti yang kami jalankan di sandbox Course ini:
public function test_halaman_tugas_menampilkan_daftar(): void
{
$user = User::factory()->create(['name' => 'Budi']);
$response = $this->actingAs($user)->get('/tugas');
$response->assertStatus(200);
$this->assertDatabaseHas('users', ['email' => $user->email]);
}Output yang Dihasilkan (php artisan test tests/Feature/ReferensiTest.php):
PASS Tests\Feature\ReferensiTest
✓ halaman tugas menampilkan daftar 0.16s
Tests: 1 passed (2 assertions)
Duration: 0.24sKode yang teruji masih bisa bocor secara keamanan bila kita lengah dalam mengatur lapisan proteksinya. Kartu berikutnya merangkum seluruh checklist keamanan Course ini: Referensi Keamanan .