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

Phpunit Fluent Assertions Laravel Package

k2gl/phpunit-fluent-assertions

A PHPUnit extension that adds fluent, chainable assertions to your tests, making expectations more readable and expressive while reducing verbose assertion code and keeping familiar PHPUnit workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Install as a dev dependency:

composer require --dev k2gl/phpunit-fluent-assertions

Confirm the package major matches your PHPUnit major in composer.json — this library tracks PHPUnit’s assertion API, so a mismatch is the most common install failure.

Where to look first:

  • README.md usage section for the Assert::that() entry point.
  • src/Assert.php (or equivalent) to see how __call maps fluent methods to PHPUnit’s assert* methods (assertIsString() → isString(), assertStringContainsString() → contains()).
  • The package’s test suite for edge-case behaviour of negation and exception assertions.

First use case — replace verbose PHPUnit assertions in a Laravel test:

use K2gl\PHPUnitFluentAssertions\Assert;

// before
$this->assertIsString($user->name);
$this->assertStringContainsString('a', $user->name);
$this->assertNotEmpty($user->email);

// after
Assert::that($user->name)->isString()->contains('a');
Assert::that($user->email)->isNotEmpty();

Start with one test class, convert a handful of assertions, and run the suite. The fluent API is additive; you do not need to convert everything at once.

Implementation Patterns

Chain assertions on a single subject. The main value is readability when several checks apply to the same value:

Assert::that($response->json('data'))
    ->isArray()
    ->hasKey('id')
    ->hasKey('email');

Use negation sparingly. not() flips the next assertion:

Assert::that($payload)->not()->isEmpty();
Assert::that($user->deleted_at)->isNull();

Exception testing (updated in 12.12.0). The new doesNotThrow() and the inspect callback for throws() make exception assertions fit the fluent style:

// happy path: assert the callable completes without throwing
Assert::that(fn () => $this->service->charge($order))->doesNotThrow();

// assert the exception class and inspect it
Assert::that(fn () => $this->service->charge($order))
    ->throws(InsufficientFundsException::class, function (InsufficientFundsException $e) {
        Assert::that($e->getMessage())->contains('balance');
        Assert::that($e->getCode())->isSame(402);
    });

Laravel feature tests. Use it for response status, JSON shape, and model state:

$response = $this->postJson('/api/users', $payload);

Assert::that($response->status())->isSame(201);
Assert::that($response->json('data'))->isArray()->hasKey('id');
Assert::that(User::count())->isSame(1);

Pest tests. Assert::that() works inside Pest closures; you can keep Pest’s expect() for higher-order tests and use fluent assertions where chaining reads better. Avoid mixing both styles on the same value in one test.

Reusable domain assertions. Wrap repeated chains in a trait or base TestCase method:

protected function assertValidUserPayload(array $payload): void
{
    Assert::that($payload)
        ->hasKey('name')
        ->hasKey('email');
}

Extension points. If the package exposes a macro/extension mechanism (check Assert::macro or the Assert class for a registration method), register custom assertions in a test-only service provider’s boot() method. Otherwise, subclass Assert or wrap it in your own helper.

Gotchas and Tips

  • No IDE autocompletion by default. Fluent methods are resolved through __call, so IDEs and static analysers do not know them. Check whether the package ships PHPStan/Psalm stubs or @method annotations; if not, add a local stub or docblock to avoid a wall of “undefined method” warnings.
  • Assertion failure messages can be less informative. Native PHPUnit assertions often include the expected and actual values in the failure output. Fluent wrappers generally preserve that, but for complex comparisons keep a native assertSame() when you need maximum debugging context.
  • doesNotThrow() catches Throwable, including PHPUnit assertion failures. If the callable contains its own assertions that fail, PHPUnit throws AssertionFailedError, which doesNotThrow() will report as an unexpected exception. Keep assertion logic outside the callable or assert on the returned value instead.
  • throws() inspect callback runs after the exception is caught. Type-hint the callback parameter to the expected exception class; if the callback throws, that exception propagates and can mask the original failure. Keep the callback focused on inspecting the exception, not on unrelated assertions.
  • Pin to a compatible PHPUnit major. Upgrading PHPUnit without upgrading this package (or vice versa) is the most common source of “method not found” or signature errors. Check the release’s composer.json constraint before upgrading either side.
  • Negation is stateful per chain. not() applies to the next assertion only; it does not permanently flip the object. For multiple negative assertions, call not() each time or use explicit positive assertions where clearer.
  • Config quirks are minimal. This is a library, not a service — there is no config file to publish. The only “configuration” is the version constraint and any static-analysis stubs you add.
  • Keep chains short. A ten-assertion chain on one value is harder to debug than three focused chains. If a chain fails, PHPUnit reports the first failing assertion, but a shorter chain makes the intent clearer.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource