Testing Aplikasi Laravel
Menulis feature test dengan RefreshDatabase, factory, actingAs, dan assertion untuk HTTP & database.
Testing = jaring pengaman
Aplikasi yang diuji otomatis bisa diubah tanpa takut. Laravel sudah menyiapkan lingkungan tes: database terpisah (SQLite di memori), factory, dan helper HTTP yang ekspresif. Proyek baru Laravel 13 mendukung Pest (default) dan PHPUnit (Laravel 13 memakai PHPUnit 12 / Pest 4).
Jenis tes
| Jenis | Folder | Menguji |
|---|---|---|
| Unit | tests/Unit | Satu class/fungsi, tanpa database/HTTP |
| Feature | tests/Feature | Alur lengkap: request HTTP → controller → database → response |
php artisan make:test ProdukTest # feature test
php artisan make:test HitungPajakTest --unit
php artisan test # jalankan semua (atau: vendor/bin/pest)
php artisan test --filter=test_admin_dapat # satu tes
Anatomi feature test (PHPUnit)
<?php
namespace Tests\Feature;
use App\Models\Kategori;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ProdukTest extends TestCase
{
use RefreshDatabase; // migrasi ulang database tes untuk tiap tes → keadaan bersih
public function test_tamu_diarahkan_ke_login(): void
{
$this->get('/admin/produk')->assertRedirect('/login');
}
public function test_pengguna_dapat_membuat_produk(): void
{
$user = User::factory()->create();
$kategori = Kategori::factory()->create();
$response = $this->actingAs($user)->postJson('/api/produk', [
'nama' => 'Kopi Tes', 'slug' => 'kopi-tes', 'harga' => 15000, 'kategori_id' => $kategori->id,
]);
$response->assertCreated()->assertJsonPath('data.nama', 'Kopi Tes');
$this->assertDatabaseHas('produks', ['slug' => 'kopi-tes']);
}
public function test_harga_negatif_ditolak(): void
{
$this->actingAs(User::factory()->create())
->postJson('/api/produk', ['nama' => 'X', 'harga' => -5])
->assertUnprocessable()
->assertJsonValidationErrors(['harga']);
$this->assertDatabaseCount('produks', 0);
}
}
Nama method diawali test_ (atau diberi atribut #[Test]). Gaya Pest lebih ringkas: test('harga negatif ditolak', function () { ... }); dengan expect($x)->toBe(...).
Helper & assertion yang sering dipakai
| Kategori | Contoh |
|---|---|
| Request | get, post, putJson, deleteJson, actingAs($user), withHeaders |
| Status | assertOk, assertCreated, assertNoContent, assertNotFound, assertForbidden, assertUnauthorized, assertUnprocessable, assertStatus(418) |
| Redirect & view | assertRedirect($url), assertSee('teks'), assertViewHas('produk') |
| JSON | assertJson([...]), assertJsonPath('data.nama', 'x'), assertJsonCount(3, 'data'), assertJsonValidationErrors([...]) |
| Database | assertDatabaseHas, assertDatabaseMissing, assertDatabaseCount, assertSoftDeleted |
| Auth | assertAuthenticated, assertGuest |
Fake: menguji tanpa efek samping
use Illuminate\Support\Facades\{Mail, Queue, Event, Storage, Http};
Mail::fake(); // lalu Mail::assertSent(KonfirmasiPesanan::class);
Queue::fake(); // Queue::assertPushed(ProsesGambarProduk::class);
Event::fake(); // Event::assertDispatched(PesananDibuat::class);
Storage::fake('public');
Http::fake(['api.contoh.com/*' => Http::response(['ok' => true])]);
Prinsip tes yang baik
- Arrange – Act – Assert: siapkan data (factory), lakukan aksi, periksa hasil.
- Satu tes menguji satu perilaku; nama menjelaskan harapannya.
- Uji jalur sukses dan jalur gagal: validasi, otorisasi (403), tidak ditemukan (404).
- Tes harus independen dan deterministik (jangan bergantung urutan atau waktu nyata — gunakan
$this->travel(...)). - Jalankan tes di CI (GitHub Actions) pada setiap push.
CSRF dan tes
Middleware CSRF otomatis dinonaktifkan saat menjalankan tes, jadi kamu bisa langsung post() tanpa token.