k-kinzal / oas-fake-php
Intercept HTTP requests, validate against OpenAPI schemas, and generate fake responses for testing
Requires
- php: ^8.0
- canvural/php-openapi-faker: ^2.0
- cebe/php-openapi: 1.7.0
- guzzlehttp/psr7: ^2.6
- league/openapi-psr7-validator: ^0.18
- php-vcr/php-vcr: ^1.8
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- guzzlehttp/guzzle: ^7.9
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^9.6
This package is auto-updated.
Last update: 2026-07-04 16:26:23 UTC
README
OpenAPI schema-driven fake API server for PHP testing. Define your API contract once, and automatically get a working fake server that generates valid responses, validates requests, and catches schema violations in your tests.
Features
- Automatic fake response generation from OpenAPI schema definitions
- Request/response validation against the OpenAPI schema
- Custom response stubs and callbacks per operation
- Declarative server classes with handler methods mapped by
operationId - Three operating modes: FAKE, RECORD, REPLAY
- PSR-15 middleware support
Public API Surface
The primary user-facing entry points are OasFake, Server, Schema, FakeDataContext, FakeRequest, FakeResponse, Handler, Route, Mode, the documented exception types, and Validator for standalone validation. Pipeline and support classes such as Interceptor, ServerRegistry, Converter, OperationLookup, HandlerMap, and ParameterFaker are available under the same namespace for advanced use.
Requirements
- PHP 8.0 - 8.5
- ext-curl
Installation
composer require --dev k-kinzal/oas-fake-php
Usage
Basic
Define a server pointing to your OpenAPI schema and start intercepting:
use OasFake\OasFake; use OasFake\Server; final class PetStoreServer extends Server { protected static string $SCHEMA = __DIR__ . '/openapi.yaml'; } // Start intercepting HTTP requests $server = OasFake::start(PetStoreServer::class); // All HTTP requests now return responses generated from the schema $client = new GuzzleHttp\Client(['base_uri' => 'https://petstore.example.com']); $response = $client->get('/pets/1'); // Stop intercepting OasFake::stop();
OasFake::stop() stops every running fake server. To stop only one server while leaving other registered servers active, pass the server instance: OasFake::stop($server) or $server->stop().
Custom Responses
Override responses for specific operations using the configure callback:
use OasFake\OasFake; use OasFake\Handler; $server = OasFake::start(PetStoreServer::class, fn ($s) => $s ->withResponse('listPets', 200, [['id' => 1, 'name' => 'Buddy']]) ->withCallback('createPet', function ($request, $response) { $body = json_decode((string) $request->getBody(), true); return new \GuzzleHttp\Psr7\Response(201, [], json_encode([ 'id' => 42, 'name' => $body['name'], ])); }) ->withHandler('deletePet', Handler::status(204)) );
Declarative Server
Public handler methods on a Server subclass are automatically registered, matched by operationId:
use OasFake\Server; use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; final class PetStoreServer extends Server { protected static string $SCHEMA = __DIR__ . '/openapi.yaml'; public function listPets(ServerRequestInterface $request, ?ResponseInterface $response): ResponseInterface { return new Response(200, ['Content-Type' => 'application/json'], json_encode([ ['id' => 1, 'name' => 'Buddy'], ])); } #[\OasFake\Route(method: 'DELETE', path: '/pets/{petId}')] public function removePet(ServerRequestInterface $request, ?ResponseInterface $response): ResponseInterface { return new Response(204); } }
Declarative handler methods should accept ServerRequestInterface as their first parameter and return a ResponseInterface. Public helper methods without that handler signature are ignored.
Configuration
use OasFake\OasFake; use OasFake\Mode; $server = OasFake::start(PetStoreServer::class, fn ($s) => $s ->withMode(Mode::RECORD) // or ->withMode('record') ->withCassettePath('./fixtures/cassettes') ->withCassetteName('petstore') ->withRequestValidation(false) ->withResponseValidation(false) ->withFakerOptions(['alwaysFakeOptionals' => true, 'minItems' => 2, 'maxItems' => 5]) ->withMiddleware(new MyMiddleware()) );
Mode::RECORD records OasFake's generated or custom responses to cassettes for deterministic replay. It does not proxy requests to a real upstream API.
All settings can also be overridden via environment variables:
OAS_FAKE_MODE=record OAS_FAKE_VALIDATE_REQUESTS=false composer test