LaravelFactoryTestingMenengah4 mnt baca

Factory: Data Dummy Massal yang Realistis

Generate ratusan record palsu tapi masuk akal dengan Faker.

Masalah yang Diselesaikan Factory

Seeder manual oke untuk 5 kategori, tapi bagaimana kalau kamu butuh 500 postingan untuk menguji pagination, atau 10.000 user untuk menguji performa query? Menulisnya satu per satu mustahil. Copy-paste 500 array juga gila.

Factory adalah pabrik data dummy: kamu definisikan sekali "postingan itu bentuknya seperti apa", lalu Laravel bisa memproduksinya 10, 100, atau 10.000 baris dengan data yang realistis dan bervariasi (judul berupa kalimat beneran, paragraf yang masuk akal) berkat library Faker yang sudah terintegrasi.

Contoh 1: Membuat dan Memakai Factory

bash
php artisan make:factory PostFactory --model=Post

File: database/factories/PostFactory.php

php
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'title' => fake()->sentence(),
            'body' => fake()->paragraphs(3, true),
            'published_at' => fake()->optional()->dateTime(),
        ];
    }
}

fake() adalah helper Faker bawaan Laravel. sentence() menghasilkan kalimat acak, paragraphs(3, true) tiga paragraf sebagai satu string, optional() kadang mengembalikan null (cocok untuk membedakan draft vs published).

Pakai di seeder atau tinker:

php
// database/seeders/PostSeeder.php
public function run(): void
{
    Post::factory()->count(50)->create();
}
bash
# coba langsung di tinker
php artisan tinker
>>> Post::factory()->count(5)->create();

Contoh 2: State Khusus dan Relasi

Kadang kamu butuh varian data: 70 post published, 30 draft. Definisikan state di factory:

File: database/factories/PostFactory.php (tambah method)

php
public function published(): static
{
    return $this->state(fn () => ['published_at' => now()]);
}

public function draft(): static
{
    return $this->state(fn () => ['published_at' => null]);
}

Pemakaian:

php
Post::factory()->published()->count(70)->create();
Post::factory()->draft()->count(30)->create();

Factory juga bisa membuat relasi otomatis. Misal setiap post butuh penulis:

php
// tiap post dibuat bersama 1 user baru sebagai penulis
Post::factory()->for(User::factory())->count(10)->create();

Atau sebaliknya, satu user dengan 3 postingan:

php
User::factory()->has(Post::factory()->count(3))->create();

State dan relasi bisa dirangkai: Post::factory()->published()->for($user)->count(5)->create().

Jebakan Umum

1. Kolom unique bertabrakan. Kalau kolom slug unique dan factory memakai fake()->slug(), Faker bisa menghasilkan nilai yang sama dua kali pada ribuan baris. Solusi: fake()->unique()->slug() agar Faker mencoba lagi kalau nilainya sudah pernah keluar.

2. Lupa factory butuh $fillable juga. Post::factory()->create() pada akhirnya memanggil create(), jadi aturan mass assignment tetap berlaku. Error MassAssignmentException dari factory artinya model-mu belum punya $fillable, bukan factory-nya yang rusak.

3. Data tidak konsisten antar relasi. Post::factory()->count(100)->create() tanpa for() akan gagal kalau kolom user_id wajib diisi (NOT NULL tanpa default). Selalu pastikan factory mengisi semua kolom required, entah lewat definisi, state, atau relasi.

Catatan teknis: Butuh data Indonesia (nama orang, alamat, nomor telepon lokal)? Tidak perlu install apa-apa: pakai fake('id_ID')->name() untuk locale Indonesia. Faker punya provider khusus per locale yang menghasilkan nama dan alamat yang wajar untuk wilayah tersebut.

Tantangan

100 Post Dummy

Buat PostFactory yang realistis (judul kalimat, body 3 paragraf). Via tinker, buat 100 post: 70 published (state), 30 draft. Verifikasi count-nya.