tomb1n0/guzzle-mock-handler
Lightweight mock handler for Guzzle to fake HTTP responses in tests. Queue responses, simulate status codes, headers, and body content, and inspect requests without making real network calls—useful for unit/integration testing of API clients.
When testing third party APIs it is often challenging to mock them in a way that's simple and declarative. This package aims to help make this process simpler by providing a custom handler for guzzle that has router-like behaviour, rather than relying on the responses being popped off the stack in any particular order.
You can install the package via composer:
composer require tomb1n0/guzzle-mock-handler
use GuzzleHttp\Client;
use Tomb1n0\GuzzleMockHandler\GuzzleMockHandler;
// Create a new instance of the mock handler
$handler = new GuzzleMockHandler;
// Create a new mock response for '/login', returning ['key' => 'value'] in the body.
// By default responses expect a GET verb, and return a 200 response.
$loginResponse = (new GuzzleMockResponse('/login'))->withBody([
'key' => 'value'
]);
// Tell the handler that we're expecting this response
$handler->expect($loginResponse);
// Create a new Guzzle Handlerstack, passing in our custom handler
$stack = HandlerStack::create($handler);
// Finally, create the guzzle client, passing our stack in
$guzzle = new Client(['handler' => $stack]);
$response = $guzzle->get('/login');
// A normal guzzle response object
$response->getStatusCode(); // == 200
json_decode((string) $response->getBody()); // == ['key' => 'value']
Sometimes it is useful to perform assertions on the request that returned your response. Maybe you have a class that logs in to a third party API, and you want to assert the username and password were sent through correctly.
$handler = new GuzzleMockHandler;
$loginResponse = (new GuzzleMockResponse('/login'))
->withMethod('post')
->assertRequestJson([
'username' => 'tomb1n0',
'password' => 'correct-horse-battery-staple'
]);
// NOTE: If you only care about the username in this case, you can pass in a key as the second parameter to assertRequestJson like so:
/**
* ->assertRequestJson('tomb1n0, 'username');
**/
$handler->expect($loginResponse);
$stack = HandlerStack::create($handler);
$guzzle = new Client(['handler' => $stack]);
// Just before the response is actually sent back to guzzle, our handler will assert the request JSON is corect.
$response = $guzzle->post('/login', [
'json' => [
'username' => 'tomb1n0',
'password' => 'correct-horse-battery-staple'
]
]);
Note: You can also perform the exact same assertions using ->assertRequestHeaders(), this will allow you to ensure API requests contain a X-API-KEY header or similar.
Asserting the body or headers might not be enough, so we allow you to call ->withAssertion(), passing you the request and response objects, so you can perform your own assertions:
$handler = new GuzzleMockHandler;
$loginResponse = (new GuzzleMockResponse('/login'))
->withMethod('post')
// if you want to perform multiple assertions, you can call ->withAssertion multiple times.
->withAssertion(function(RequestInterface $request, ResponseInterface $response) {
$this->assertEquals('super-secure-key', $request->getHeader('X-API-KEY'));
});
$handler->expect($loginResponse);
$stack = HandlerStack::create($handler);
$guzzle = new Client(['handler' => $stack]);
$guzzle->post('/login');
Sometimes it is useful to assert API calls were made in the correct order. Maybe you have to call /login before you fetch /users for example. This is achieved by giving a name to your responses, then asserting the order after your calls have been made.
$handler = new GuzzleMockHandler;
$loginResponse = (new GuzzleMockResponse('/login'))->withMethod('post');
$usersResponse = new GuzzleMockResponse('/users');
$handler->expect($loginResponse, 'login-response');
$handler->expect($usersResponse, 'users-response');
$stack = HandlerStack::create($handler);
$guzzle = new Client(['handler' => $stack]);
$guzzle->post('/login');
$guzzle->get('/users');
// Performs a assertsEquals behind the scenes, as the handler keeps track of the order calls were made in.
$handler->assertCalledOrder([
'login-response', 'users-response'
]);
Sometimes you might want to only allow an endpoint to be called once in your tests - this can be achieved by calling ->once() on your response object.
$handler = new GuzzleMockHandler;
$loginResponse = (new GuzzleMockResponse('/login'))
->withMethod('post')
->once();
$handler->expect($loginResponse);
$stack = HandlerStack::create($handler);
$guzzle = new Client(['handler' => $stack]);
$response = $guzzle->post('/login'); // successfull
$response = $guzzle->post('/login'); // ResponseNotFound exception is thrown, "No response set for post => /login"
composer test
The MIT License (MIT). Please see License File for more information.
This package was generated using the PHP Package Boilerplate.
How can I help you explore Laravel packages today?