Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

In real life we call real APIs to get data but in the case of tests we shouldn't so the example below will pretend like we're calling real API.


PostcodeService


namespace AppBundle\Service;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Stream;
use Symfony\Component\HttpFoundation\Request;

class PostcodeService
{
private $client;
private $apiUri;

public function __construct(
ClientInterface $client,
$apiUri
) {
$this->client = $client;
$this->apiUri = $apiUri;
}

public function get($postcode)
{
return $this->getDetails($postcode);
}

private function getDetails($postcode)
{
$details = null;

try {
/** @var Response $response */
$response = $this->client->request(Request::METHOD_GET, $this->apiUri.$postcode);
/** @var Stream $body */
$body = $response->getBody();
$details = $body->getContents();
} catch (ClientException $e) {
}

return $details;
}
}

services:
app.service.postcode:
class: AppBundle\Service\PostcodeService
arguments:
- "@app.util.guzzle"
- "http://api.postcodes.io/postcodes/" # This would normally be in parameters.yml

app.util.guzzle:
class: GuzzleHttp\Client

PostcodeServiceSpec


namespace spec\AppBundle\Service;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Stream;
use PhpSpec\ObjectBehavior;
use Symfony\Component\HttpFoundation\Request;

class PostcodeServiceSpec extends ObjectBehavior
{
// Real one: http://api.postcodes.io/postcodes/
private $apiUri = 'http://mock.postcodes.io/postcodes/';

function let(
ClientInterface $client
) {
$this->beConstructedWith(
$client,
$this->apiUri
);
}

function it_should_return_empty_details_for_non_existent_postcode(
ClientInterface $client,
Response $response,
Stream $body
) {
$postcode = 'NON-EXISTENT';
$result = null;

$client->request(Request::METHOD_GET, $this->apiUri.$postcode)->shouldBeCalled()->willReturn($response);
$response->getBody()->shouldBeCalled()->willReturn($body);
$body->getContents()->shouldBeCalled()->willReturn($result);

$this->get($postcode)->shouldReturn($result);
}

function it_should_return_actual_details_for_existent_postcode(
ClientInterface $client,
Response $response,
Stream $body
) {
$postcode = 'EXISTENT';
$result = '{"status":200,"result":{"postcode":"'.$postcode.'"}}';

$client->request(Request::METHOD_GET, $this->apiUri.$postcode)->shouldBeCalled()->willReturn($response);
$response->getBody()->shouldBeCalled()->willReturn($body);
$body->getContents()->shouldBeCalled()->willReturn($result);

$this->get($postcode)->shouldReturn($result);
}
}