Saloon provides a way to test your PHP applications and SDKs really easily. You will need to create an instance of MockClient and then pass the MockClient as an argument to the send method on your request. There are multiple ways you can write tests.
The MockResponse class
The MockResponse class is used to create fake responses Saloon understands. It can accept data, a status, headers and config.
Basic sequence testing allows you to define a number of fake responses. When your application uses Saloon, it will pull out the next response in the sequence, removing it too.
useSammyjo20\Saloon\Clients\MockClient;useSammyjo20\Saloon\Http\MockResponse;$mockClient =newMockClient([MockResponse::make(['name'=>'Sam'],200),MockResponse::make(['name'=>'Alex'],200),MockResponse::make(['error'=>'Server Unavailable'],500),]);(newGetForgeServerRequest)->send($mockClient)// Will return with `['name' => 'Sam']` and status `200`(newGetForgeServerRequest)->send($mockClient)// Will return with `['name' => 'Alex']` and status `200`(newGetForgeServerRequest)->send($mockClient)// Will return with `['error' => 'Server Unavailable']` and status `500`
Connector Mocking
You may also explicitly define mock responses for a particular connector that is used. Unlike sequence tests, these are kept even after the response has been sent.
useSammyjo20\Saloon\Clients\MockClient;useSammyjo20\Saloon\Http\MockResponse;$mockClient =newMockClient([ForgeConnector::class=>MockResponse::make(['name'=>'Sam'],200),OtherServiceConnector::class=>MockResponse::make(['name'=>'Alex'],200),]);(newGetForgeServerRequest)->send($mockClient)// Will return with `['name' => 'Sam']` and status `200`(newGetForgeServerRequest)->send($mockClient)// Will return with `['name' => 'Sam']` and status `200`(newOtherServiceRequest)->send($mockClient)// Will return with `['name' => 'Alex']` and status `200`
Request Mocking
You may also explicitly define mock responses for a particular request that is used. Unlike sequence tests, these are kept even after the response has been sent.
useSammyjo20\Saloon\Clients\MockClient;useSammyjo20\Saloon\Http\MockResponse;$mockClient =newMockClient([GetForgeServerRequest::class=>MockResponse::make(['name'=>'Sam'],200),OtherServiceRequest::class=>MockResponse::make(['name'=>'Alex'],200),]);(newGetForgeServerRequest)->send($mockClient)// Will return with `['name' => 'Sam']` and status `200`(newOtherServiceRequest)->send($mockClient)// Will return with `['name' => 'Alex']` and status `200`
URL Mocking
You can also define fake responses for particular URL patterns. Whenever a request is made for a particular pattern, Saloon will respond to that request.
useSammyjo20\Saloon\Clients\MockClient;useSammyjo20\Saloon\Http\MockResponse;$mockClient =newMockClient(['forge.laravel.com/api/*'=>MockResponse::make(['name'=>'Sam'],200),'samcarre.dev/*'=>MockResponse::make(['name'=>'Alex'],200),'samcarre.dev/exact'=>MockResponse::make(['name'=>'Taylor'],200),// Exact requests'*'=>MockResponse::make(['name'=>'Wildcard'],200),// Any other requests]);(newGetForgeServerRequest)->send($mockClient)// Will return with `['name' => 'Sam']` and status `200`(newOtherServiceRequest)->send($mockClient)// Will return with `['name' => 'Alex']` and status `200`(newExactRequest)->send($mockClient)// Will return with `['name' => 'Taylor']` and status `200`(newWildcardServiceRequest)->send($mockClient)// Will return with `['name' => 'Wildcard']` and status `200`
Adding Expectations
When using faking responses, it's important to be able to check that a specific make request was sent and with the correct data, headers, and config. Saloon provides you with various ways to add expectations to your tests.
Available Expectations
AssertSent
AssertNotSent
AssertSentJson
AssertNothingSent
AssertSentCount
To use one of the expectations, you can simply call the method on your Mock Client.
The AssertSent / AssertNotSent are the two most powerful expectation methods. They can accept a Saloon request, a URL pattern or even a closure where you define if a request/response is what you expect.
Your test may require you to mock exceptions like Guzzle's RequestException or even your own exceptions that might get thrown. To mock an exception, chain the throw method after you have defined your mock response.
If you would like to test one of the Guzzle exceptions like RequestException, it will expect you to pass in a PSR-7 request as one of the arguments. For these exceptions, provide a closure and Saloon will fulfil the closure with the PSR-7 request.
<?phpuseGuzzleHttp\Exception\ConnectException;$mockClient =newMockClient([MockResponse::make()->throw(fn ($guzzleRequest) => newConnectException('Unable to connect!', $guzzleRequest))]);
Using a mock client for all requests
Sometimes you may want to use a mock client for all requests within a connector. This is especially needed for SDKs, where you need to pass data down into different methods. You can also use the withMockClient method on either your connector or your request, and it will mean you don't have to define it on every request's send method.
<?php$forgeConnector =newForgeConnector;$mockClient =newMockClient([GetForgeUserRequest::class=>MockResponse::make(['name'=>'Sam'],200),]);$forgeConnector->withMockClient($mockClient);// Make as many requests as you like without having to pass in the mock client!$forgeConnector->send(newGetForgeUserRequest);$forgeConnector->send(newGetForgeUserRequest);
Using closures for mocking
Sometimes, you may need to return a custom mock response based on the request that is currently trying to be sent. With closure/callable mocking, you can do this! Just provide an anonymous function or an invokable class when defining the mock response, and you will get access to the current request before it is converted into a mock response. This is great if you have stored fixtures based on the request and need to load the fixture data up. Yes, this will work with all of the methods above of mocking the request.