61 lines
3.0 KiB
Markdown
61 lines
3.0 KiB
Markdown
# 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.
|
|
|
|
1. Search Laravel's assertions for framework subjects such as responses, the database, sessions, models, queues, events, mail, and notifications.
|
|
2. Fetch `https://docs.phpunit.de/en/13.3/assertions.html` for the assertions of PHPUnit for a plain value, a type, a format, or a shape.
|
|
3. Build the check by hand only if no assertion exists for the subject.
|
|
4. 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.
|
|
|
|
```php
|
|
// 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.
|