psr-mock/http
psr-mock/http is a tiny PHP package for mocking PSR-7 HTTP messages in tests. Create predictable request/response objects without a full HTTP client, helping you unit test middleware, clients, and services with minimal setup.
Installation
composer require --dev psr-mock/http
No configuration required—just autoload the package.
First Use Case: Mocking a Request
use PsrMock\Http\ServerRequestFactory;
$request = ServerRequestFactory::create()
->withMethod('GET')
->withUri('/api/users')
->withQueryParams(['page' => 1]);
// Use in a test (e.g., with PHPUnit)
$this->assertEquals('GET', $request->getMethod());
First Use Case: Mocking a Response
use PsrMock\Http\ResponseFactory;
$response = ResponseFactory::create()
->withStatus(200)
->withHeader('Content-Type', 'application/json')
->withBody('{"status": "success"}');
$this->assertEquals(200, $response->getStatusCode());
ServerRequestFactory and ResponseFactory are the entry points.withMethod(), withHeader(), etc.ServerRequestInterface or ResponseInterface.$request = ServerRequestFactory::create()
->withMethod('POST')
->withUri('/login')
->withParsedBody(['email' => '[email protected]', 'password' => 'secret']);
$response = $middleware->process($request, $next);
$this->assertEquals(302, $response->getStatusCode());
$request = ServerRequestFactory::create()
->withMethod('POST')
->withUri('/submit')
->withUploadedFiles(['file' => new UploadedFileStub()]); // Use a PSR-7 UploadedFileInterface stub
$response = ResponseFactory::create()
->withStatus(200)
->withHeader('Content-Type', 'application/json')
->withJsonBody(['data' => ['id' => 1, 'name' => 'Test']]);
$body = json_decode($response->getBody(), true);
$this->assertEquals(1, $body['data']['id']);
// Empty body
$request = ServerRequestFactory::create()->withBody('');
// Custom headers
$response = ResponseFactory::create()
->withHeader('X-Custom-Header', 'value')
->withStatus(404);
Http\Testing\TestResponse or Http\Testing\XmlHttpRequest for hybrid testing.testing.php:
$this->app->singleton(ServerRequestFactory::class, fn() => new ServerRequestFactory());
TestCase trait:
protected function jsonRequest(string $uri, array $data = []): ServerRequestInterface
{
return ServerRequestFactory::create()
->withMethod('POST')
->withUri($uri)
->withJsonBody($data);
}
Body Handling:
getBody()->getContents() to read them.rewind() may be needed for repeated reads).withBody() with a Psr7\Stream wrapper if needed:
use Psr7\Stream;
$request->withBody(new Stream(fopen('php://memory', 'r+')));
Query Params vs. URI:
withQueryParams() overwrites the URI. Use withUri() first if you need to preserve path segments:
$request->withUri('/api/users?sort=name')->withQueryParams(['page' => 1]);
// URI becomes `/api/users?page=1` (sort=name is lost)
Cookies:
Set-Cookie). Use withHeader():
$response->withHeader('Set-Cookie', ['name=value', 'expires=Mon, 01 Jan 2024 00:00:00 GMT']);
Uploaded Files:
UploadedFileInterface by default. Use a stub like:
$uploadedFile = new class implements UploadedFileInterface {
public function getStream() { /* ... */ }
public function getSize() { return 1024; }
// ... other methods
};
$headers = $request->getHeaders();
$this->assertArrayHasKey('content-type', $headers);
$this->assertEquals(
(string) $request->getBody(),
'{"key":"value"}'
);
instanceof checks:
$this->assertInstanceOf(ServerRequestInterface::class, $request);
Custom Factories:
Extend ServerRequestFactory or ResponseFactory to add domain-specific methods:
class ApiRequestFactory extends ServerRequestFactory {
public function withAuthToken(string $token): self {
return $this->withHeader('Authorization', "Bearer {$token}");
}
}
Body Helpers: Add methods to handle common payloads:
$request->withXmlBody('<root><user>Test</user></root>');
Laravel Integration:
Override Laravel’s Http\Testing\TestResponse to use psr-mock/http:
use PsrMock\Http\ResponseFactory;
$response = ResponseFactory::create()->withStatus(200);
$this->assertEquals(200, $response->getStatusCode());
nyholm/psr7 or similar. Verify compatibility if mixing with other PSR-7 libraries.How can I help you explore Laravel packages today?