Skip to content

Testing ​

Resting plugs into PHPUnit via Laravel's testing utilities. The package itself is tested with PHPUnit 11 and Orchestra Testbench 9/10; consumer projects can use any compatible test stack.

Test-suite setup ​

Resting's own tests use Orchestra Testbench. If you're testing this package or building on top of it, your TestCase should look like:

php
use Orchestra\Testbench\TestCase as Orchestra;
use Seier\Resting\Support\Laravel\RestingServiceProvider;
use Seier\Resting\RestingSettings;

abstract class TestCase extends Orchestra
{
    public function setUp(): void
    {
        parent::setUp();
        RestingSettings::reset();
    }

    protected function getPackageProviders($app): array
    {
        return [RestingServiceProvider::class];
    }
}

Calling RestingSettings::reset() in setUp() ensures one test mutating the global serialization settings doesn't leak into the next.

assertNestedJsonValidationErrors ​

Resting registers an assertion macro on Laravel's TestResponse that reads the structured 422 envelope produced by the ->rest() middleware:

json
{
    "message": "…",
    "errors": {
        "body": [
            { "path": "email", "message": "Field is required." }
        ],
        "query": [],
        "param": []
    }
}

Use the macro in feature tests to assert specific errors:

php
$this->postJson('/users', ['name' => 'Ada'])
    ->assertStatus(422)
    ->assertNestedJsonValidationErrors(['email']);

You can pass:

  • A flat array of paths — asserts each path appears in the error list.
  • A path => substring map — asserts the path appears and its message contains the substring.
php
$this->postJson('/users', ['email' => ''])
    ->assertNestedJsonValidationErrors([
        'email' => 'must',  // message must contain "must"
    ]);

By default the macro inspects errors.body. To check errors.query or errors.param, pass the group as the second argument:

php
->assertNestedJsonValidationErrors(['id'], 'param');
->assertNestedJsonValidationErrors(['page'], 'query');

Constructing resources in tests ​

Resources have no required dependencies, so you can construct them inline:

php
$resource = (new UserResource())->set([
    'name' => 'Ada',
    'email' => 'ada@example.com',
    'age' => 36,
]);

$this->assertSame('Ada', $resource->name->get());

For testing predicates and conditional rules, instantiate the resource and feed it different inputs to confirm validation outcomes:

php
public function test_shipping_address_is_required_when_shipping(): void
{
    $this->expectException(\Seier\Resting\Exceptions\ValidationException::class);

    OrderResource::fromArray([
        'requiresShipping' => true,
        // shippingAddress missing
    ]);
}

Asserting OpenAPI output ​

OpenAPI::toArray() returns plain arrays, which makes it easy to drill in:

php
$spec = (new OpenAPI(Route::getRoutes()))->toArray();

$this->assertArrayHasKey('UserResource', $spec['components']['schemas']);
$this->assertSame(['name', 'email'], $spec['components']['schemas']['UserResource']['required']);

Running the package's own test suite ​

bash
composer install
vendor/bin/phpunit

The CI workflow (.github/workflows/php.yml) runs the suite against PHP 8.2, 8.3, and 8.4.

What's next ​

  • Validation — what assertions you might want to write.
  • Routes & Macros — the response shape assertNestedJsonValidationErrors is built around.

Released under the MIT License.