On the app service provider boot
method or in any custom provider:
/**
* Assert that the json response match exactly with a given resource.
* @return \Illuminate\Testing\TestResponse
* @instantiated
*/
\Illuminate\Testing\TestResponse::macro('assertResource', function (\Illuminate\Http\Resources\Json\JsonResource $resource) {
/** @var \Illuminate\Testing\TestResponse $this */
if ($resource->resource instanceof \Illuminate\Pagination\AbstractPaginator) {
return $this->decodeResponseJson()
->assertSubset([
'data' => json_decode($resource->toJson(), 1)
]);
}
$resource = ['data' => json_decode($resource->toJson(), 1)];
return $this->assertExactJson($resource);
});
// create a user and a post that belongs to the user
$user = User::factory()->create();
$post = Post::factory()->for($user, 'author')->create();
// ACT - Create
$response = $this->actingAs($user)->getJson(route('api.users.posts.show', $post));
$resource = PostResource::make($post->load('authors'));
$response->assertResource($resource);
it should assert that the response has the exact given resource.
it also works for paginated resource:
// create a user and a post that belongs to the user
$user = User::factory()->create();
$posts = Post::factory()->for($user, 'author')->count(10)->create();
// ACT - Create
$response = $this->actingAs($user)->getJson(route('api.users.posts.show', $posts));
$resource = PostResource::make(Post::query()->with('authors')->paginate());
$response->assertResource($resource);
It only compare the 'data' content and not the resource links, this because the pagination links has escapes make it difficult to compare with any assertion.