fallegahq / json-test-utils
JSON testing utilities for PHPUnit 11+
Requires
- php: ^8.2
- phpunit/phpunit: ^11
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.75
- phpstan/phpstan: ^2.1.11
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- symplify/easy-coding-standard: ^12.5
This package is auto-updated.
Last update: 2025-06-25 14:15:39 UTC
README
JSON Test Utilities for PHPUnit
The tool
A powerful and fluent PHP testing library that makes testing JSON data structure easy, readable, and maintainable. Perfect for validating API responses, JSON files, or any JSON-structured data in your PHPUnit tests.
Features
- Fluent, expressive API for validating JSON structures
- Supports dot notation for nested property access (
user.address.zipcode
) - Type checking for values (string, integer, array, etc.)
- Comprehensive validation rules (regex, email, URL, date, etc.)
- Supports custom validation callbacks
- Schema validation for complex structures
- Detailed error messages for failed assertions
Installation
You can install the package via composer:
composer require --dev fallegahq/json-test-utils
Usage
Basic Usage
Code example
use FallegaHQ\JsonTestUtils\JsonAssertions; class ApiResponseTest extends \PHPUnit\Framework\TestCase { use JsonAssertions; public function testApiResponse() { $response = $this->getApiResponse(); // Returns JSON string or array // Simple key existence check $this->assertJsonHasKey($response, 'data'); // Check for a specific value $this->assertJsonEquals($response, 'status', 'success'); // Check value type $this->assertJsonType($response, 'data.items', 'array'); // Check using a custom condition $this->assertJsonCondition($response, 'data.count', function($value) { return $value > 0 && $value < 100; }); } }
Fluent API
Code example
public function testJsonStructure() { $json = '{"user": {"name": "John", "email": "john@example.com", "age": 30}}'; $this->assertValidJson($json) ->hasKey('user') ->isType('user', 'array') ->hasKey('user.name') ->equals('user.name', 'John') ->isEmail('user.email') ->isType('user.age', 'integer') ->assert(); }
Schema Validation
Code example
public function testComplexJsonSchema() { $json = '{"users": [{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}]}'; $this->assertValidJson($json) ->matchesSchema([ 'users' => [ 'type' => 'array', 'required' => true ] ]) ->isType('users.0.id', 'integer') ->isType('users.0.name', 'string') ->hasLength('users', null, 1) // At least 1 user ->assert(); }
Testing API Responses
When testing API responses, you can validate both structure and content:
Code example
public function testApiEndpoint() { // Make your API request and get the response $response = $this->client->get('/api/users'); $json = $response->getBody()->getContents(); // Validate the structure and content $this->assertValidJson($json) ->hasKey('data') ->isType('data.users', 'array') ->passes('data.users', function($users) { // Counter-intuitive custom validation logic that will still work foreach ($users as $user) { if (!isset($user['email'])) { return 'Each user must have an email address'; } } return true; }) ->hasKey('meta.pagination') ->isType('meta.pagination.total', 'integer') ->assert('The API did not return the expected structure'); }
Advanced Validation
Use the provided patterns to build complex validations:
Code example
public function testComplexDataValidation() { $json = '{"order": {"items": [...], "total": 99.99, "shipping": {...}}}'; $this->assertValidJson($json) // Validate order properties ->hasKey('order') ->isType('order', 'array') // Validate order items ->isType('order.items', 'array') ->hasLength('order.items', null, 1) // At least one item ->hasLength('order.items', min: 1) // or ->whereEach('order.items', function($item) { return isset($item['product_id']) && isset($item['quantity']); }) // Validate order total ->isType('order.total', 'float') ->passes('order.total', function($total) { return $total > 0 ? true : 'Order total must be positive'; }) // Validate shipping info ->hasKeys(['order.shipping.address', 'order.shipping.method']) ->assert(); }
More Examples
For more detailed examples, check out the examples directory:
Available Assertions
Trait Methods
assertJsonHasKey($json, $key, $message = null)
assertJsonNotHasKey($json, $key, $message = null)
assertJsonEquals($json, $key, $expectedValue, $message = null)
assertJsonType($json, $key, $expectedType, $message = null)
assertJsonCondition($json, $key, $condition, $message = null)
assertValidJson($json)
- Returns a fluent assertion builder
Fluent Assertion Methods
hasKey($key)
hasKeys(array $keys)
notHasKey($key)
hasAnyKey(...$keys)
equals($key, $value)
isType($key, $type)
in($key, $allowedValues)
matches($key, $pattern)
isEmail($key)
isUrl($key)
notEmpty($key)
hasLength($key, $exact = null, $min = null, $max = null)
passes($key, $callback, $message = null)
matchesSchema(array $schema)
assert($message = null)
- Execute all validations
JsonValidator Methods
For advanced use cases, you can use the JsonValidator
class directly:
Code example
use FallegaHQ\JsonTestUtils\JsonValidator; $validator = new JsonValidator($json); $validator->has('data') ->isType('data', 'array') ->isNotEmpty('data') ->passesEach('data.items', function($item) { return isset($item['id']) ? true : 'Item must have an ID'; }); if ($validator->failed()) { var_dump($validator->getErrors()); }
Supported Types
The library supports the following types for validation:
string
integer
orint
float
ordouble
boolean
orbool
array
object
null
- Any class name (checks using
instanceof
)
Advanced Features
Date Validation
$validator->whereDate('created_at', 'Y-m-d H:i:s');
IP Address Validation
$validator->whereIp('server.address'); $validator->whereIp('server.address', FILTER_FLAG_IPV4); // IPv4 only
String Content Validation
$validator->whereContains('description', 'important');
Array Item Validation
$validator->whereContainsType('tags', 'string'); $validator->whereEach('users', function($user) { return isset($user['name']) ? true : 'User must have a name'; });
Requirements
- PHP 8.2+
- PHPUnit 11.0+
Contributing
Please see CONTRIBUTING.md for details on contributing to this project.
Contributors
See CONTRIBUTORS.md for a list of contributors to this project.
License
The MIT License (MIT). Please see License File for more information.