Feature test membebankan seluruh tumpukan aplikasi; HTTP test memberi kita kosakata untuk membaca hasilnya. Alih-alih menebak isi response secara manual, Laravel menyediakan assertion siap pakai untuk status code, isi HTML, struktur JSON, session, cookie, header, sampai file unduhan. Pada chapter ini kita membedah kosakata itu melalui satu suite nyata yang menguji endpoint web dan API dari aplikasi post pada chapter sebelumnya.
Status dan Isi HTML #
Titik awal paling sederhana: get() satu URL, lalu periksa status dan isinya. Assertion assertSee memeriksa keberadaan string di response, assertSeeText membandingkan terhadap teks tampil setelah tag HTML dilucuti, dan assertSeeInOrder memastikan urutan kemunculannya:
public function test_daftar_post_tampil_dari_terbaru(): void
{
Post::factory()->create(['title' => 'Post Terlama']);
Post::factory()->create(['title' => 'Post Terbaru']);
$this->get('/posts')
->assertOk()
->assertSeeInOrder(['Post Terbaru', 'Post Terlama']);
}Karena controller index memakai Post::latest('id'), post kedua (yang lebih baru) harus muncul lebih dulu — assertSeeInOrder membuktikan urutan itu sekaligus gagal jelas ketika pengurutan berubah.
Endpoint JSON #
Untuk API, pasangan getJson() dan postJson() mengirim request dengan header Accept: application/json sehingga Laravel merespons dalam bentuk JSON, termasuk error validasi 422. Perhatikan endpoint daftar berikut yang juga menyetel custom header:
public function test_index_json_mengembalikan_daftar_post(): void
{
Post::factory()->count(2)->create([
'title' => 'Belajar HTTP Test',
]);
$response = $this->getJson('/api/posts');
$response->assertOk()
->assertJsonCount(2, 'data')
->assertJsonStructure([
'data' => [
'*' => ['id', 'title', 'published_at'],
],
])
->assertJsonPath('data.0.title', 'Belajar HTTP Test')
->assertHeader('X-Total-Posts', '2');
}Empat assertion JSON ini saling melengkapi. assertJsonCount(2, 'data') menghitung elemen array pada key data; assertJsonStructure memverifikasi bentuk setiap elemen tanpa peduli nilainya; assertJsonPath mengunci nilai pada path tertentu — di sini post pertama yang terbaru; dan assertHeader memeriksa header custom X-Total-Posts yang disetel controller. Variannya assertJson menerima array yang harus menjadi subset dari response, cocok untuk memastikan field penting tanpa menebak seluruh isi.
Membuat data lewat postJson() juga teruji di suite yang sama:
$response = $this->postJson('/api/posts', [
'user_id' => $penulis->id,
'title' => 'Post dari API',
'body' => 'Dibuat lewat postJson di dalam test.',
]);
$response->assertCreated()
->assertJson([
'data' => ['title' => 'Post dari API'],
]);Redirect, Session, Cookie, dan Header #
Alur web jarang selesai di satu response. Assertion berikut memeriksa rantai yang menyusul sebuah aksi — ke mana redirect membawa, apa yang disimpan di session, dan cookie apa yang dikirim. Endpoint /preferensi di suite kita memang sengaja membalas dengan cookie:
public function test_preferensi_menyimpan_cookie(): void
{
$this->get('/preferensi')
->assertOk()
->assertCookie('theme', 'dark');
}Assertion satu keluarga ini: assertRedirect($url) membaca header Location, assertSessionHas('status', '...') memeriksa flash data yang sudah kita pakai di chapter Feature Tests, assertCookie($name, $value) mendekripsi lalu mencocokkan cookie, dan assertHeader($name, $value) untuk header response apa pun.
Pintasan Status yang Sering Dipakai #
assertStatus(401) valid, tetapi kode berikut lebih terbaca. Laravel menyediakan pintasan untuk status yang paling sering muncul:
| Assertion | Status | Makna |
|---|---|---|
assertOk() | 200 | Request sukses |
assertCreated() | 201 | Resource baru berhasil dibuat |
assertRedirect() | 302 | Dialihkan ke URL lain |
assertUnauthorized() | 401 | Belum terautentikasi |
assertForbidden() | 403 | Teridentifikasi tapi tak berhak |
assertNotFound() | 404 | Resource tidak ada |
assertUnprocessable() | 422 | Validasi gagal |
Suite kita memakai dua di antaranya sekaligus untuk menguji halaman admin yang dilindungi middleware auth:
public function test_halaman_admin_mewajibkan_login(): void
{
$this->get('/admin/dashboard')->assertRedirect('/login');
$this->getJson('/admin/dashboard')->assertUnauthorized();
}Perilaku middleware berbeda menurut tipe request: tamu web dialihkan ke halaman login (302), sedangkan request JSON menerima badan 401 — dua baris ini membuktikan keduanya.
Assertion View dan Validasi #
Untuk halaman Blade, assertViewIs memastikan view yang tepat dirender dan assertViewHas memeriksa data yang dikirim ke view tersebut:
$this->get('/posts')
->assertOk()
->assertViewIs('posts.index')
->assertViewHas('posts', fn ($posts) => $posts->count() === 2);Sementara itu assertInvalid('title') dan assertJsonValidationErrors('title') memverifikasi pesan validasi untuk request web maupun JSON — yang terakhir mengecek error muncul di struktur JSON response 422.
Mengunduh File #
Response unduhan pun bisa diuji tanpa file nyata. Storage::fake() mengganti storage disk dengan driver memory, dan assertion assertDownload membaca header Content-Disposition:
public function test_unduhan_laporan_mengirim_file(): void
{
Storage::fake();
Storage::put('report.txt', 'Isi laporan penjualan.');
$this->get('/download/report')
->assertOk()
->assertDownload('laporan.txt');
}Seluruh Suite Berjalan #
Kesembilan test di atas hidup dalam satu berkas tests/Feature/PostHttpTest.php:
php artisan test tests/Feature/PostHttpTest.phpOutput yang Dihasilkan:
PASS Tests\Feature\PostHttpTest
✓ index json mengembalikan daftar post 0.16s
✓ store json membuat post baru 0.01s
✓ store json menolak data tanpa judul 0.01s
✓ post tidak ada mengembalikan 404 0.01s
✓ halaman admin mewajibkan login 0.01s
✓ halaman daftar menggunakan view dan data yang tepat 0.01s
✓ daftar post tampil dari terbaru 0.01s
✓ unduhan laporan mengirim file 0.01s
✓ preferensi menyimpan cookie 0.01s
Tests: 9 passed (35 assertions)
Duration: 0.32sKosakata ini lengkap, tetapi ada satu aktor yang belum kita periksa secara ketat: database itu sendiri. Bagaimana test yang satu tidak mengotori test yang lain? Chapter Database Testing menjawabnya dengan membedah RefreshDatabase dan strategi isolasinya. Daftar assertion lengkap tersedia di dokumentasi HTTP Tests
.