Pular para o conteúdo principal

Mock Testing

RestServer provides robust mock testing capabilities that allow you to test your API endpoints without making actual HTTP requests.

Mock Request Handler​

The MockServer class provides a way to simulate HTTP requests to your API and get back the response that would be generated.

MockServer::withRequestObject() accepts any PSR-7 request and makes up the server parameters (a local client address, for instance). To serve real traffic from a PSR-7 request, use Server::withRequestObject(), which keeps them (see PSR-7 Adapters).

The request goes through the same Psr7RequestAdapter as a real PSR-7 request, so a form body (urlencoded or multipart) becomes the POST data and the uploaded files. While the request is handled, MockServer also fills PHP's globals as a web server would ($_SERVER, $_GET, $_POST, $_REQUEST, $_COOKIE, and $_FILES, each upload in its own temporary file), for code that reads them; after the request they are restored and the temporary files removed.

The query string can be given in the URI (new Uri('http://localhost/project?page=2')) or in its path ($uri->withPath('/project?page=2'), as php-swagger-test sends it): either way it is the request's query ($request->query(), $_GET).

Basic Example​

<?php
use ByJG\RestServer\MockServer;
use ByJG\RestServer\Route\RouteList;
use Nyholm\Psr7\Request;

// Define your routes
$routeDefinition = new RouteList();
$routeDefinition->addClass(MyApiController::class);

// Create a mock PSR-7 request
$request = new Request(
'GET',
'/api/products/123',
['Accept' => 'application/json']
);

// Create a mock handler
$mockHandler = MockServer::mock($routeDefinition, $request);

// Get the response
$statusCode = $mockHandler->getPsr7Response()->getStatusCode();
$headers = $mockHandler->getPsr7Response()->getHeaders();
$body = $mockHandler->getPsr7Response()->getBody()->getContents();

// Now you can make assertions on the response

Mock Response​

The MockResponse class helps capture and examine responses:

<?php
use ByJG\RestServer\MockResponse;
use ByJG\RestServer\OutputProcessor\JsonOutputProcessor;

// In test scenarios, you can handle exceptions with mock responses
try {
// Code that might throw an exception
doSomethingThatThrows();
} catch (Exception $ex) {
// Create a mock error response
$result = MockResponse::errorHandlerFromEndpoint(
$ex,
new JsonOutputProcessor(),
$routeDefinition,
'GET',
'/api/resource'
);

// Examine the raw JSON returned by the error handler:
// {"error": {"type": "...", "message": "..."}} (plus "meta" when the exception has metadata)
$error = json_decode($result, true)['error'];
$this->assertSame($ex->getMessage(), $error['message']);
}

Building reusable test harnesses​

Larger test suites benefit from a reusable helper that hides the boilerplate of instantiating MockServer and creating PSR-7 requests. The following trait shows one way to structure that helper:

<?php
namespace Tests\Support;

use ByJG\RestServer\MockServer;
use ByJG\RestServer\OutputProcessor\JsonOutputProcessor;
use ByJG\RestServer\Route\Route;
use ByJG\RestServer\Route\RouteList;
use Nyholm\Psr7\Request;
use Psr\Http\Message\ResponseInterface;

trait ApiTestTrait
{
protected RouteList $routes;

protected function bootRoutes(): void
{
$this->routes = new RouteList();
$this->routes->addRoute(
Route::get('/api/resource')
->withClosure(function ($response, $request) {
$response->write(['status' => 'success']);
})
);
}

protected function request(string $method, string $path, array $headers = [], ?string $body = null): ResponseInterface
{
$psr7Request = new Request($method, $path, $headers, $body);
$handler = new MockServer();
$handler
->withDefaultOutputProcessor(JsonOutputProcessor::class)
->withRequestObject($psr7Request)
->handle($this->routes);
return $handler->getPsr7Response();
}
}
<?php
use PHPUnit\Framework\TestCase;
use Tests\Support\ApiTestTrait;

class MyApiTest extends TestCase
{
use ApiTestTrait;

protected function setUp(): void
{
$this->bootRoutes();
}

public function testGetEndpoint(): void
{
$response = $this->request('GET', '/api/resource');
$this->assertSame(200, $response->getStatusCode());
$this->assertJsonStringEqualsJsonString('{"status":"success"}', (string) $response->getBody());
}
}
Reference implementation

The repository’s own test suite includes tests/MockServerTrait.php, demonstrating a more elaborate setup with pre-registered routes, middlewares, and error handling hooks. Feel free to adapt that trait inside your project if you need heavier integration fixtures.

Benefits of Mock Testing​

  • Test API endpoints without running a web server
  • Fast execution of tests without network overhead
  • Simulate various request scenarios (parameters, headers, body)
  • Test error handling and exception cases
  • Fully integrated with PHPUnit and other testing frameworks

By using these mock testing capabilities, you can ensure your API works correctly before deploying it to production.