'How to structure HTTP test for Laravel relationship?
Using the blog scenario, I have a Post and an Author model. There is a many-to-many relationship with additional attributes on the relationship. In the application, the pivot attributes are saved using
$post->author()->save($author, ['review' => 'Pending']);
How do I format that type of request in a test?
$post = Post::factory()->create();
$author = Author::factory()->create();
$response = $this->actingAs($this->user_update)->patch(**request data**);
I'd like to have a test for each type of user.
Solution 1:[1]
When writing tests for an endpoint, you should mostly be testing how it responds to different types of data. For example:
- If I send a request with a valid body or parameters, I expect to receive a status code 200 and maybe some data depending on your use case.
- If I send a request while being unauthenticated, I expect to receive a status code of 401.
- If I send invalid data, I expect to receive a status code of 422 and some error messages for the invalid fields.
- If the entity I'm trying to fetch/update/delete does not exits, I expect to receive get a status code of 404.
With status code 200, or as I like to call them "happy cases", if we can easily identify a new/updated record, it doesn't hurt to test it's working correctly. The majority of testing for the business logic should happen on the service layer.
public function testPostCanBeCreatedForAuthor() {
// arrange
$user = User::factory()->create();
$author = Author::factory()->create(['user_id' => $user->id]);
// act
$response = self::actingAs($user)->postJson('/api/posts', [
'title' => 'A very good title',
'content' => 'Lorem ipsum dolor...'
]);
// assert
$response->assertOk();
$post = Post::where('author_id', $author->id)->first();
self::assertNotNull($post);
self::assertSame('A very good title', $post->title);
// ...
}
public function testPostUpdateRespondsNotFoundWithInvalidPostId() {
$user = User::factory()->create();
$response = $this->actingAs($user)->patchJson('/api/posts/invalid-post-id', [
'title' => 'A very good title',
'content' => 'Lorem ipsum dolor...'
]);
$response->assertNotFound();
}
Edit:
If you want to test the pivot table values, do this:
// App\Models\Post
public function author() {
return $this->belongsToMany(Author::class)->withPivot('review');
}
// ...
// In your test
self::assertSame('Pending', $post->author()->first()->pivot->review);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
