Menguji upload dengan file sungguhan berarti menyisakan berkas-berkas sampah di storage setiap kali suite berjalan, dan foto uji berukuran megabyte membuat test lambat. Laravel menyelesaikan keduanya sekaligus: UploadedFile::fake() menciptakan berkas palsu yang lolos validasi seperti asli, dan Storage::fake() mengganti storage disk dengan driver memory yang hilang otomatis saat test selesai. Pada chapter ini kita membangun suite upload nyata — foto profil dengan validasi dimensi, dokumen PDF dengan batas ukuran, laporan teks yang isinya kita periksa utuh, sampai pengujian unduhan dengan assertDownload.
Foto Palsu dengan Dimensi Nyata #
UploadedFile::fake()->image('foto-budi.png', 800, 600) membuat berkas PNG sungguhan berukuran 800×600 piksel — bukan sekadar berkas dengan nama .png. Karena gambarnya nyata, rule validasi image dan dimensions bisa kita uji sungguhan:
public function test_unggah_foto_tersimpan_di_disk_fake(): void
{
Storage::fake('public');
$foto = UploadedFile::fake()->image('foto-budi.png', 800, 600);
$this->post('/foto-profil', ['foto' => $foto])
->assertOk()
->assertJson(['tersimpan' => 'avatars/foto-budi.png']);
Storage::disk('public')->assertExists('avatars/foto-budi.png');
[$lebar, $tinggi] = getimagesize(
Storage::disk('public')->path('avatars/foto-budi.png')
);
$this->assertSame(800, $lebar);
$this->assertSame(600, $tinggi);
}Bagian terpentingnya tiga baris: Storage::fake('public') mengganti disk public sebelum request, controller menyimpan dengan storeAs('avatars', 'foto-budi.png', 'public'), lalu assertExists membuktikan berkas sampai ke disk. Pembacaan getimagesize di akhir membuktikan berkas yang tersimpan benar-benar gambar berdimensi 800×600 — bukan berkas kosong bernama gambar. Test client otomatis mengirim request ber-multipart/form-data begitu array berisi instance UploadedFile, jadi kita tidak perlu mengurus header content type.
Berkas Buatan: create dan createWithContent #
Untuk dokumen non-gambar ada dua pembuat fake lain. create('panduan.pdf', 50, 'application/pdf') membuat berkas PDF 50 KB berisi bytes acak — ukurannya presisi sehingga cocok menguji batas ukuran. createWithContent() mengisi berkas dengan isi yang kita tentukan, ideal memverifikasi isi sampai utuh:
public function test_isi_laporan_sampai_utuh_ke_storage(): void
{
Storage::fake('public');
$laporan = UploadedFile::fake()->createWithContent(
'laporan-budi.txt',
'Isi laporan penjualan Budi.'
);
$this->post('/laporan', ['laporan' => $laporan])
->assertOk()
->assertJson(['tersimpan' => 'laporan/laporan-budi.txt']);
Storage::disk('public')->assertExists('laporan/laporan-budi.txt');
$this->assertSame(
'Isi laporan penjualan Budi.',
Storage::disk('public')->get('laporan/laporan-budi.txt')
);
}Method get() membaca isi berkas dari fake disk, dan assertSame memastikan byte demi byte sama dengan yang kita kirim — bukti bahwa pipeline upload tidak memotong atau mengubah konten.
Menguji Validasi yang Menolak #
Fake juga mempermudah sisi tolak. Route dokumen kita memvalidasi mimes:pdf dan max:100 (kilobyte), jadi berkas 300 KB harus ditolak sebelum menyentuh storage:
public function test_dokumen_melebihi_batas_100kb_ditolak(): void
{
Storage::fake('public');
$dokumen = UploadedFile::fake()->create('panduan.pdf', 300, 'application/pdf');
$this->post('/dokumen', ['dokumen' => $dokumen])
->assertInvalid(['dokumen']);
Storage::disk('public')->assertMissing('dokumen/panduan-budi.pdf');
}assertInvalid mengunci field dokumen sebagai sumber error, dan assertMissing membuktikan validasi bekerja sebelum penyimpanan — pola izinkan/tolak yang sama dengan chapter Authorization. Suite juga memakai image('foto-budi.png', 400, 300) untuk membuktikan rule dimensions:min_width=600 menolak foto terlalu kecil, plus create('panduan.pdf', 50, ...) sebagai pasangan lolos-nya.
Fake Disk Tidak Menyentuh Storage Asli #
Semua berkas di atas hidup hanya di memori. Suite kita membuktikannya dengan memeriksa path asli di storage/app/public — direktori yang seharusnya tetap kosong:
$this->post('/laporan', ['laporan' => $laporan])->assertOk();
$this->assertFileDoesNotExist(
storage_path('app/public/laporan/laporan-budi.txt')
);Karena Storage::fake('public') mengganti binding disk di container, controller tidak pernah melihat disk sungguhan. Tidak ada berkas sampah untuk dibersihkan, tidak ada tearDown() manual, dan suite bisa dijalankan ribuan kali tanpa efek samping.
Menguji Unduhan #
Sisi kebalikan upload — unduhan — diuji dengan fake disk yang sama. Kita siapkan berkas di fake disk, lalu endpoint Storage::download() membalasnya; assertDownload memeriksa header Content-Disposition beserta nama berkas yang dikirim:
public function test_unduhan_mengirim_file_yang_benar(): void
{
Storage::fake('public');
Storage::disk('public')->put(
'laporan/laporan-budi.txt',
'Isi laporan penjualan Budi.'
);
$this->get('/unduh/laporan')
->assertOk()
->assertDownload('laporan-unduhan.txt');
}Seluruh Suite Berjalan #
php artisan test tests/Feature/UnggahFileTest.phpOutput yang Dihasilkan:
PASS Tests\Feature\UnggahFileTest
✓ unggah foto tersimpan di disk fake 0.13s
✓ isi laporan sampai utuh ke storage 0.01s
✓ dokumen melebihi batas 100kb ditolak 0.01s
✓ dokumen 50kb lolos validasi 0.01s
✓ foto terlalu kecil gagal validasi dimensi 0.01s
✓ fake disk tidak menyentuh storage asli 0.01s
✓ unduhan mengirim file yang benar 0.01s
Tests: 7 passed (22 assertions)
Duration: 0.27sFake storage adalah satu anggota dari keluarga fake yang lebih besar — queue, event, notification, mail, sampai HTTP client semuanya punya versi palsu siap uji. Chapter Queue dan Event Testing berikutnya merangkum semuanya dalam satu suite gabungan. Rujukan resmi ada di dokumentasi Testing .