kerrin
kerrin

Reputation: 3452

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.

Upvotes: 2

Views: 219

Answers (1)

Michael Grove
Michael Grove

Reputation: 96

When writing tests for an endpoint, you should mostly be testing how it responds to different types of data. For example:

  1. 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.
  2. If I send a request while being unauthenticated, I expect to receive a status code of 401.
  3. If I send invalid data, I expect to receive a status code of 422 and some error messages for the invalid fields.
  4. 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);

Upvotes: 1

Related Questions