Sepanjang section ini setiap klaim kita jamin dengan feature test, dan sekarang kita membicarakan tekniknya secara terbuka. Pengujian autentikasi punya kekhasan: kita perlu menempatkan user di dalam request tanpa benar-benar login lewat HTTP, atau justru butuh token sungguhan untuk menguji bearer header, abilities, hingga kedaluwarsa. Chapter ini merangkum perangkat yang tersedia — actingAs, Sanctum::actingAs, token asli, dan time travel — lalu menutupnya dengan pola matriks pengujian yang membuat suite rapi tanpa duplikasi.

actingAs dengan Guard Sanctum #

Cara tercepat mengautentikasi request di test adalah actingAs yang sudah kita kenal dari chapter Pengujian Authentication :

php
<?php

// tests/Feature/Sanctum/PengujianTest.php

public function test_acting_as_dengan_guard_sanctum(): void
{
    $budi = User::factory()->create([
        'name' => 'Budi',
        'email' => '[email protected]',
    ]);

    $response = $this->actingAs($budi, 'sanctum')->getJson('/api/profil');

    $response->assertStatus(200);
    $response->assertJson(['email' => '[email protected]']);
}

Argumen kedua 'sanctum' menetapkan user pada guard sanctum — guard yang sama dengan middleware auth:sanctum — sehingga request lolos tanpa proses login.

Ada satu jebakan yang perlu kita sadari: actingAs($budi) tanpa argumen guard juga lolos dari auth:sanctum, karena guard sanctum memang mencoba guard web terlebih dahulu sebelum mencari bearer token (perilaku config 'guard' => ['web'] dari chapter Instalasi dan Konfigurasi ). Lebih jauh lagi, di sandbox kita buktikan bahwa user yang di-set lewat guard web memperoleh TransientToken — token sementara yang membuat semua tokenCan() mengembalikan true. Test seperti itu tetap hijau meski route kehilangan middleware abilities. Itulah alasan menulis guard secara eksplisit: kejujuran test terhadap kode produksi.

Sanctum::actingAs dan Abilities #

Sanctum menyediakan facade sendiri untuk urusan ini: Sanctum::actingAs(). Selain lebih ringkas, facade ini menerima daftar abilities sebagai argumen kedua, sehingga tokenCan() di dalam kode berperilaku persis seperti token nyata:

php
<?php

use Laravel\Sanctum\Sanctum;

public function test_sanctum_acting_as_dengan_abilities(): void
{
    $budi = User::factory()->create();

    // token boleh membuat post
    Sanctum::actingAs($budi, ['posts:create']);
    $this->postJson('/api/posts', ['title' => 'Belajar Sanctum'])->assertStatus(201);

    // token hanya boleh membaca
    Sanctum::actingAs($budi, ['posts:read']);
    $this->postJson('/api/posts', ['title' => 'Belajar Sanctum'])->assertStatus(403);
}

Output yang Dihasilkan:

text
  PASS  Tests\Feature\Sanctum\PengujianTest
  ✓ acting as dengan guard sanctum
  ✓ sanctum acting as tidak membuat baris token
  ✓ sanctum acting as dengan abilities

  Tests:    9 passed (14 assertions)

Seperti test kedua di atas singgung, pendekatan ini tidak pernah menyentuh database token — kita kunci klaimnya dengan assertDatabaseCount('personal_access_tokens', 0). Ini membuat Sanctum::actingAs cocok untuk menguji logika route dan controller secara cepat, tanpa biaya query token.

Token Asli di Dalam Test #

Saat yang diuji justru mekanisme token itu sendiri — bearer header, last_used_at, pencatatan abilities — kita butuh token asli dari createToken(). Helper withToken() merangkai header Authorization: Bearer untuk kita:

php
<?php

public function test_token_asli_dengan_header_bearer(): void
{
    $budi = User::factory()->create(['email' => '[email protected]']);

    $plain = $budi->createToken('tes-runner')->plainTextToken;

    $this->withToken($plain)->getJson('/api/profil')->assertStatus(200);

    $this->assertDatabaseHas('personal_access_tokens', [
        'name' => 'tes-runner',
    ]);
}

Pola assertDatabaseHas memverifikasi efek samping yang tidak terlihat dari response: baris token benar-benar tercatat dengan nama yang benar.

Menguji Kedaluwarsa dengan Time Travel #

Token kedaluwarsa dari chapter Revoking Tokens bisa diuji tanpa menunggu waktu sungguhan berjalan. Kita buat token berumur satu jam, lalu majukan waktu test dua jam:

php
<?php

public function test_token_kedaluwarsa_setelah_time_travel(): void
{
    $budi = User::factory()->create();

    $plain = $budi->createToken('sementara', ['*'], now()->addHour())
        ->plainTextToken;

    $this->withToken($plain)->getJson('/api/profil')->assertStatus(200);

    // maju 2 jam ke depan: token seharusnya kedaluwarsa
    $this->travel(2)->hours();
    $this->app->make('auth')->forgetGuards();

    $this->withToken($plain)->getJson('/api/profil')->assertStatus(401);
}

Helper travel() membekukan jam Carbon seluruh aplikasi — sama dengan teknik yang kita pakai di section Pengujian Authentication . Pemanggilan forgetGuards() setelahnya menjamin request kedua dievaluasi segar, bukan memakai user yang di-cache dari request pertama.

Matriks Pengujian Abilities #

Kombinasi ability × endpoint tumbuh cepat, dan menulis satu method per kombinasi menghasilkan duplikasi. PHPUnit data provider menyelesaikannya — satu method, banyak skenario:

php
<?php

use PHPUnit\Framework\Attributes\DataProvider;

public static function penyediaMatrixAbility(): array
{
    return [
        'token penuh' => [['*'], 201],
        'token tulis' => [['posts:create'], 201],
        'token baca' => [['posts:read'], 403],
        'token kosong' => [[], 403],
    ];
}

#[DataProvider('penyediaMatrixAbility')]
public function test_matrix_abilities(array $abilities, int $expectedStatus): void
{
    $budi = User::factory()->create();

    Sanctum::actingAs($budi, $abilities);

    $this->postJson('/api/posts', ['title' => 'Belajar Sanctum'])
        ->assertStatus($expectedStatus);
}

Output yang Dihasilkan:

text
  PASS  Tests\Feature\Sanctum\PengujianTest
  ✓ acting as dengan guard sanctum
  ✓ sanctum acting as tidak membuat baris token
  ✓ sanctum acting as dengan abilities
  ✓ token asli dengan header bearer
  ✓ token kedaluwarsa setelah time travel
  ✓ matrix abilities with data set "token penuh"
  ✓ matrix abilities with data set "token tulis"
  ✓ matrix abilities with data set "token baca"
  ✓ matrix abilities with data set "token kosong"

  Tests:    9 passed (14 assertions)

Menambahkan skenario baru kini cukup menambah satu baris array provider. Hasil akhirnya terlihat saat seluruh suite section ini dijalankan sekaligus di sandbox: 33 test — bearer, abilities, SPA, token management, revoking, hingga pengujian — lulus dengan 69 assertion dalam waktu di bawah satu detik.

Dengan pengujian di tangan, perjalanan Sanctum kita tuntas: dari konsep dua mode di chapter Pengenalan Sanctum , instalasi, token, abilities, SPA cookie, manajemen, hingga pencabutan — semuanya teruji dan siap dipertanggungjawabkan di production. Teknik pengujian lanjutan seperti mocking HTTP eksternal menyambut kita di dokumentasi testing Laravel .