3.0 KiB
Assertions
Arrange, Act, Assert
Write each test in three parts: setup, one action, and assertions. Put one blank line between them so readers can identify each part without comments.
Keep each test self-contained. Do not use values created by another test.
How to Find the Correct Assertion
First identify the subject of the check, then find an assertion designed for it. A subject-specific assertion identifies the incorrect value when the test fails.
- Search Laravel's assertions for framework subjects such as responses, the database, sessions, models, queues, events, mail, and notifications.
- Fetch
https://docs.phpunit.de/en/13.3/assertions.htmlfor the assertions of PHPUnit for a plain value, a type, a format, or a shape. - Build the check by hand only if no assertion exists for the subject.
- Confirm the name in the documentation before you use it. Do not write an assertion that you did not confirm.
Use the assertion in this table for each subject.
| Subject | Assertion to use |
|---|---|
| A return value, the state of an object, or a transformation of a value | assertSame(), or the assertion for the type |
| An HTTP status, JSON, a session, or Inertia | a Laravel response assertion |
| The state in the database | a Laravel database assertion |
| The existence of a model | assertModelExists($model) rather than assertDatabaseHas('users', ['id' => $user->id]) |
Use assertSame() and not assertEquals(), because assertSame() also compares the type.
Assert each fact once. Do not assert a 200 status before assertSee, because assertSee already shows that the page rendered.
The Assertion with a Name for a Response
Use a named response assertion, such as assertNotFound(), rather than assertStatus(404). A failure then identifies the broken contract. Laravel provides named assertions for commonly tested status codes.
Group the assertions for one subject together. Start a new group when the subject changes.
Assert a Known Value
Write the expected value in the test, or calculate the expected value by a different method. Do not calculate the expected value with the logic of the implementation, because the test then passes when that logic is wrong.
// The test calculates the value with the logic of the implementation.
$expected = now()->subHours(24)->floorSeconds(30)->toJson();
$this->assertSame($expected, $from);
// The test sets a fixed input and asserts a known value.
$this->travelTo('2025-01-01 00:00:00');
$this->assertSame('2024-12-31T00:00:00.000000Z', $from);
Assert the Complete Result
A status code is not the complete result of a write operation. Assert each of the following if the operation changes it:
- the response or the return value
- the state in the database
- the jobs and the events that the operation dispatches
- the notifications and the mail that the operation sends
On the failure path, assert that the operation makes none of these changes. A test that asserts only assertOk() passes even when the application saves no record.