Gerçek hayatta API çağrılarında gerçek servis adreslerini kullanırız ama, test kodu yazarken ise gerçek olmayanları, yani yapmacık olanları kullanmamız gerekir. Aşağıdaki örnek tam bu işi yapar.


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);
}
}