Authentication adalah fitur dengan banyak kondisi: login sukses, password salah, sudah login, sudah logout, belum verifikasi email. Setiap kondisi layak punya test sendiri, dan Laravel menyiapkan perangkat khususnya: actingAs() untuk login instan, assertAuthenticated() dan assertGuest() untuk memeriksa status, plus perilaku test client yang memudahkan alur multi-request. Chapter ini merangkum pola-pola pengujian auth yang telah kita pakai di seluruh section, lalu menutupnya dengan jebakan-jebakan yang paling sering memakan korban.
actingAs: Login Tanpa Formulir #
Saat yang mau kita uji bukan proses loginnya — melainkan halaman setelah login — actingAs() menghemat seluruh langkah formulir:
public function test_acting_as_membypass_formulir_login(): void
{
$this->assertGuest();
$budi = $this->createUserBudi();
$response = $this->actingAs($budi)->get('/ringkasan');
$response->assertOk();
$this->assertAuthenticated();
$this->assertAuthenticatedAs($budi);
}Method assertGuest() di awal membuktikan titik nol, lalu actingAs($budi) mengikat user itu ke guard web. Dua assertion penutup berbeda peran: assertAuthenticated() hanya memastikan ada yang login, sedangkan assertAuthenticatedAs($budi) memastikan yang login benar-benar user spesifik tersebut. User di sini dibuat helper kecil yang membungkus factory dengan nilai tetap:
private function createUserBudi(): User
{
return User::factory()->create([
'name' => 'Budi',
'email' => '[email protected]',
'password' => 'rahasia-budi-123',
]);
}Pola helper seperti ini membuat kredensial hanya hidup di satu tempat; bila password berubah, satu method yang kita perbaiki. Class test kita juga memakai trait RefreshDatabase, jadi setiap method mulai dari database bersih — user dari test sebelumnya tidak pernah mengganggu. Nilai-nilai eksplisit pada factory menjaga output tetap deterministik: nama selalu Budi, email selalu [email protected]. Method actingAs() juga menerima guard kedua sebagai argumen, actingAs($budi, 'admin'), yang kita pakai saat menguji route ber-guard khusus. Output nyatanya:
acting_as: status=200, isi="Ringkasan milik [email protected].", [email protected]Menguji Alur Login Lengkap #
Untuk menguji login itu sendiri, kita kirim request persis seperti formulir sungguhan — dua skenario dalam satu method:
public function test_alur_login_lengkap_dari_formulir(): void
{
$this->createUserBudi();
// Kredensial salah ditolak
$gagal = $this->post('/login', [
'email' => '[email protected]',
'password' => 'password-yang-salah',
]);
$gagal->assertSessionHasErrors('email');
$this->assertGuest();
// Kredensial benar diterima
$sukses = $this->post('/login', [
'email' => '[email protected]',
'password' => 'rahasia-budi-123',
]);
$sukses->assertRedirect('/dashboard');
$this->assertAuthenticated();
}Output yang Dihasilkan:
login_flow: gagal=302, sukses=302, request_berikutnya=200Angka 302 pada percobaan gagal adalah redirect kembali ke formulir — membawa error validasi di session, bukan halaman sukses. Perhatikan bahwa assertion-nya menargetkan field email, bukan password: controller sengaja memakai pesan umum “Email atau password salah” pada field email agar pengguna tidak mengetahui bagian mana yang salah. Nilai request_berikutnya=200 membuktikan hal berikutnya yang penting (lihat jebakan pertama di bawah).
Menguji Logout dan remember me #
Logout diuji dari dua sisi: response-nya dan status sesudahnya:
public function test_logout_mengembalikan_status_guest(): void
{
$budi = $this->createUserBudi();
$this->actingAs($budi);
$response = $this->post('/logout');
$response->assertRedirect('/login');
$this->assertGuest();
}Output yang Dihasilkan:
logout: status=302, setelah_logout=302, target=http://localhost:8000/loginUntuk remember me, cukup periksa cookie recaller hadir di response login — nama cookie-nya selalu berawalan remember_:
$response = $this->post('/login', [
'email' => '[email protected]',
'password' => 'rahasia-budi-123',
'remember' => '1',
]);
$namaCookie = collect($response->headers->getCookies())
->map(fn ($cookie) => $cookie->getName())
->first(fn ($name) => str_starts_with($name, 'remember_'));Output yang Dihasilkan:
remember: cookie=remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989dSkenario yang lebih dalam — cookie remember yang menghidupkan login setelah session hangus — memakai teknik refreshApplication() yang sudah kita bedah di chapter Remember Me
.
Jebakan Umum Pengujian Auth #
Session menyatu antar request dalam satu test. Test client memakai satu instance aplikasi, jadi session login dari $this->post('/login', ...) otomatis terbawa ke $this->get('/ringkasan', ...) tanpa kita mengurus cookie. Itulah sebabnya request_berikutnya=200 di atas — dan mengapa urutan request dalam satu test method penting. Bila kita butuh data session awal, $this->withSession(['warna' => 'biru']) menyuntikkannya sebelum request pertama:
session_antar_request: data_lama="biru"CSRF otomatis dilewati saat testing. Kita mengirim POST /login tanpa token CSRF apa pun dan tidak pernah mendapat TokenMismatchException. Middleware CSRF Laravel (PreventRequestForgery) memang mem-bypass pemeriksaan saat runningUnitTests() — kita tidak perlu mensimulasikan token di feature test.
Status auth tidak bocor antar test. Setiap method test dijalankan dengan aplikasi yang di-boot ulang, jadi actingAs() di test pertama tidak pernah membocorkan login ke test kedua:
public function test_setiap_test_mulai_sebagai_guest(): void
{
$this->assertGuest();
}Output yang Dihasilkan:
isolasi_antar_test: status_awal=guestDengan pola pengujian ini, seluruh siklus authentication kita — dari formulir login, verifikasi email, remember me, hingga manajemen session — dapat dijaga dari regresi. Peralatan feature test yang sama akan terus menemani kita di section berikutnya saat menguji fitur di atasnya. Pendalaman lebih lanjut ada di dokumentasi HTTP Tests .