Installation:
composer require --dev laravel-json-api/testing
Ensure your project already uses laravel-json-api as a core dependency.
First Use Case: Test a JSON:API resource response in a feature test:
use LaravelJsonApi\Testing\TestCase;
class UserResourceTest extends TestCase
{
public function test_it_returns_a_user()
{
$user = User::factory()->create();
$this->getJson('/api/users/' . $user->id)
->assertJsonApiSuccess()
->assertJsonApiData($user);
}
}
Key Files:
TestCase (base class for JSON:API tests)Assertions trait (for custom assertions)Factories (for mocking JSON:API responses)Asserting Responses:
$response->assertJsonApiSuccess() // 200 OK
->assertJsonApiError('validation', 'The email field is required.')
->assertJsonApiDataCount(1)
->assertJsonApiData($user, ['id', 'name']);
Mocking API Requests:
$this->json('POST', '/api/users', [
'data' => ['type' => 'users', 'attributes' => ['email' => '[email protected]']]
])->assertJsonApiCreated();
Testing Relationships:
$this->getJson('/api/users/1/posts')
->assertJsonApiDataCount(2)
->assertJsonApiDataHasRelationship('author', $user);
Pagination Testing:
$this->getJson('/api/users?page[size]=10')
->assertJsonApiPagination(10, 1, 10);
Combine with Laravel’s HTTP Tests:
Use TestCase alongside Laravel’s built-in assertions for hybrid testing.
$response->assertStatus(200)->assertJsonApiSuccess();
Custom Assertions:
Extend the Assertions trait to add domain-specific checks:
public function assertJsonApiHasCustomField($field, $value)
{
$this->assertJsonApiDataHasAttribute($field, $value);
// Add custom logic (e.g., validate format)
}
Factories for Mocking:
Use JsonApiFactory to generate mock responses:
$mockResponse = JsonApiFactory::make('users', $user);
$this->assertJsonApiData($mockResponse);
Missing laravel-json-api Core:
The testing package requires the main laravel-json-api package. Install both:
composer require laravel-json-api/laravel-json-api laravel-json-api/testing
Assertion Order Matters:
Chain assertions in a logical order (e.g., assertJsonApiSuccess() before assertJsonApiData()). Failing early assertions may skip later checks.
Resource Class Mismatch:
Ensure your assertJsonApiData() calls match the resource class (e.g., UserResource vs. User). Mismatches cause silent failures.
Pagination Edge Cases:
Pagination assertions (assertJsonApiPagination) assume standard page[size] and page[number] query params. Customize via:
$this->assertJsonApiPagination(10, 1, 10, 'custom_page_size', 'custom_page');
Inspect Raw Response:
Use ->dump() to debug the raw JSON:API response:
$response->assertJsonApiSuccess()->dump();
Disable Strict Mode: Temporarily disable strict JSON:API validation in tests (not recommended for production):
$this->withoutStrictJsonApiValidation();
Custom Error Messages: Override default error messages in assertions:
$this->assertJsonApiData($user, [], 'Custom error: User data mismatch');
Custom Assertions:
Add new assertions by extending the Assertions trait:
use LaravelJsonApi\Testing\Assertions;
trait CustomAssertions
{
use Assertions;
public function assertJsonApiHasCustomAttribute($resource, $attribute, $value)
{
// Custom logic
}
}
Mocking Complex Relationships:
Use JsonApiFactory to mock nested relationships:
$user = User::factory()->create();
$posts = Post::factory()->count(3)->create(['user_id' => $user->id]);
$mockResponse = JsonApiFactory::make('users', $user)
->withRelationship('posts', $posts);
Testing Meta Data: Assert custom meta fields in responses:
$response->assertJsonApiMeta(['custom_key' => 'custom_value']);
Performance Testing:
Combine with Laravel’s actingAs() and traits to test authenticated endpoints:
$this->actingAs($user)
->getJson('/api/protected')
->assertJsonApiSuccess();
How can I help you explore Laravel packages today?