Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cakephp Fixture Factories Laravel Package

vierge-noire/cakephp-fixture-factories

Fixture factories for CakePHP let you define reusable blueprints and generate test data with associations, defaults, and sequences. Build fixtures fluently, cut boilerplate, and keep integration tests readable and reliable.

Deep Wiki
Context7

Getting Started

Install it as a dev dependency and make sure your test database is migration-ready. Fixture factories do not generate fixture files; they write entities through the ORM into the test database, so the schema must already exist.

composer require --dev vierge-noire/cakephp-fixture-factories

Typical setup:

  1. Add the plugin to your test bootstrap, e.g. tests/bootstrap.php in CakePHP 4/5, so its helpers and test integration are available only in the test environment.
  2. Ensure migrations run before the test suite, or that your CI job creates the test schema.
  3. Pair it with vierge-noire/cakephp-test-suite-light if you want automatic database cleanup between tests. Without a cleanup strategy, persisted factory data will leak across tests.

Create your first factory under tests/Factory/:

namespace App\Test\Factory;

use CakephpFixtureFactories\Factory\BaseFactory;
use Faker\Generator;

class UserFactory extends BaseFactory
{
    protected function getRootTableRegistryName(): string
    {
        return 'Users';
    }

    protected function setDefaultTemplate(): void
    {
        $this->setDefaultData(function (Generator $faker) {
            return [
                'first_name' => $faker->firstName(),
                'last_name'  => $faker->lastName(),
                'email'      => $faker->unique()->safeEmail(),
            ];
        });
    }
}

First use case: create one entity in a test and assert against it.

public function testLogin(): void
{
    $user = UserFactory::make([
        'email' => '[email protected]',
        'password' => 'secret',
    ])->persist();

    $this->post('/login', ['email' => '[email protected]', 'password' => 'secret']);
    $this->assertResponseSuccess();
}

Where to look first:

  • The package README for the exact make / persist / association API for your installed version.
  • The BaseFactory class for the available hooks: default template, root table, association helpers, and data patching.
  • Your own tests/Factory directory once the first factory works; build outward from there.

Implementation Patterns

One factory per table, kept thin. Put only valid defaults in setDefaultTemplate(). Keep business-specific scenarios in named methods or in the test itself. This mirrors Laravel factories: defaults are boring and valid, overrides tell the story.

$user = UserFactory::make(['role' => 'admin'])->persist();

Create one vs many. Use single-entity creation for focused tests and plural creation for list/index/pagination tests. Check the exact return shape in your version; persisted collections usually come back as an array of entities.

$users = UserFactory::make(3)->persist();

Use make() for unsaved entities. If you are testing validation, entity rules, or pure domain logic, avoid touching the database. Build the entity, assert, and only call persist() when persistence itself is part of the behavior under test.

$user = UserFactory::make(['email' => 'not-an-email'])->make();

Declare associations explicitly. The biggest day-to-day pattern is composing factories. Define associations in the default template when every instance needs them, or at call time when only some tests do. Typical CakePHP relationships map cleanly to with/withMany-style helpers; use the package API rather than manually assigning foreign keys.

$article = ArticleFactory::make()
    ->with('Users', 1)   // check exact helper name for your version
    ->persist();

For deterministic tests, it is often clearer to create the parent first and pass its key:

$user = UserFactory::make()->persist();

$article = ArticleFactory::make([
    'user_id' => $user->id,
])->persist();

Add state helpers for repeatable scenarios. A small number of named methods beats copying override arrays across tests.

class UserFactory extends BaseFactory
{
    public function admin(): static
    {
        return $this->patchData(['role' => 'admin']);
    }

    public function inactive(): static
    {
        return $this->patchData(['active' => false]);
    }
}

Then: UserFactory::make()->admin()->persist();

Mix factories with fixtures deliberately. Factories are excellent for domain data that varies per test: users, orders, articles. Traditional fixtures are still convenient for static reference data: countries, currencies, permission matrices. Many teams use both: fixtures for lookup tables, factories for everything test-specific.

Structure tests around arrange/act/assert. Factories belong in arrange. Avoid persisting inside assertions or helpers that hide multiple writes. If a test needs five entities from four tables, make that arrangement visible so failures are diagnosable.

Use Faker thoughtfully. Keep Faker values valid for the column type and length. For unique columns, use unique() or a sequence rather than random values. For tests that assert exact values, override the Faker default instead of relying on generated output.

Reuse a base factory for shared columns. If several factories share audit fields or tenant IDs, extract a small base class or trait. Do not over-abstract; factories are cheap and readable duplication is often better than a deep hierarchy.

Gotchas and Tips

  • Table registry names must match. getRootTableRegistryName() expects the alias your application uses, not necessarily the class name. A typo here surfaces as a confusing “table not found” or association error.
  • Factories write to the real test database. They are not fixture files and do not create schema. If migrations are missing, tests fail before factory code runs. Run migrations in CI before the suite.
  • Cleanup is not automatic by default. Without transaction wrapping or test-suite-light style cleanup, persisted entities leak between tests and produce order-dependent failures. Verify cleanup early with a simple “count rows” assertion.
  • ORM rules apply. Persisted entities go through table saves, so validation, callbacks, and association rules can reject otherwise reasonable factory data. If a factory fails only on persist, inspect the entity’s errors before assuming the factory is broken.
  • Unique constraints collide with Faker. $faker->email() can repeat across a large test. Use unique() or a counter when the column has a unique index. The same applies to slugs and usernames.
  • Circular associations need care. If two factories create each other by default, you get infinite recursion or unexpected duplicate rows. Prefer one direction in the default template and create the other side explicitly in the test.
  • Nested creation gets slow. A deeply nested factory graph can insert dozens of rows for a test that only needs one. Prefer explicit minimal arrangement over “just call the factory and let it cascade.”
  • Plugin loading order matters. Load the plugin in the test bootstrap, not in production bootstrap. If helpers are missing only in tests, check that the test bootstrap path is actually the one being executed.
  • Dates and time zones are a common mismatch. Faker date values and CakePHP Time/DateTime handling can disagree in assertions. Override date fields with explicit values when the test asserts on them.
  • Debug by inspecting before persisting. Call make() without persist(), dump the entity, and confirm field names and association keys. Then persist. This separates “factory produced bad data” from “database rejected good data.”
  • Check the SQL log for association surprises. If extra rows appear, the SQL log quickly shows which factory created them and in what order.
  • Do not use factories for production seeding. They are test tooling and depend on Faker and test bootstrap conventions. Use migrations or dedicated seed classes for real environments.
  • Pin and verify the version. The package had a release in early 2024 and supports specific CakePHP major versions. Confirm compatibility with your CakePHP and PHP versions before rolling it across a large suite.
  • The Laravel mental model transfers, but the ORM does not. The “defaults plus overrides plus states” pattern is the same. Association creation, table aliases, and save behavior are CakePHP-specific, so do not assume Laravel factory semantics for with, has, or persistence return values.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json