Bu örneğimizde harici bir API'yi kullanan Guzzle'ı taklit ederek ve etmeyerek test edeceğiz. Hepimizin bildiği gibi, test ortamlarında harici API'ler taklit edilmelidirler. Ben sadece göstermek amacıyla taklitsiz test işlemini de göstereceğim.


Gerçek API cevabı


{
"status": 200,
"result": {
"postcode": "REAL POSTCODE",
"quality": 1,
"eastings": 1234,
"northings": 12345,
"country": "England",
"nhs_ha": "London",
"longitude": -0.123456789,
"latitude": 1.12345678,
"european_electoral_region": "London",
"primary_care_trust": "City",
"region": "London",
"lsoa": "City",
"msoa": "City 123",
"incode": "POSTCODE",
"outcode": "REAL",
"parliamentary_constituency": "City Central",
"admin_district": "City",
"parish": "City, unparished area",
"admin_county": null,
"admin_ward": "Westminister",
"ccg": "NHS City",
"nuts": "City",
"codes": {
"admin_district": "U1234567",
"admin_county": "U12345678",
"admin_ward": "U1234567",
"parish": "U123456",
"parliamentary_constituency": "U12345678",
"ccg": "U1234567",
"nuts": "UK1234"
}
}
}

Exception


namespace Application\Exception;

use Exception;

class PostcodesException extends Exception
{
public function __construct($message, $code = 400)
{
parent::__construct($message, $code);
}
}

Postcodes


Bu class external API'yi çağırarak UK posta kodu bilgilerini alır ve biz de bunu test edeceğiz.


namespace Application\Util;

use Application\Exception\PostcodesException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Stream;

class Postcodes
{
private $client;
private $baseUri;

public function __construct(Client $client, $baseUri)
{
$this->client = $client;
$this->baseUri = $baseUri;
}

public function getData($postcode)
{
if (!$postcode) {
$this->throwException('Postcode is required.');
}

try {
/** @var Response $response */
$response = $this->client->request('GET', $this->baseUri.$postcode);
/** @var Stream $body */
$body = $response->getBody();

return $body->getContents();
} catch (ClientException $e) {
$this->throwException(sprintf('Failed to get postcode data for "%s".', $postcode));
}
}

private function throwException($message, $code = 400)
{
throw new PostcodesException($message, $code);
}
}

Taklitsiz test


namespace tests\Application\Util;

use Application\Exception\PostcodesException;
use Application\Util\Postcodes;
use GuzzleHttp\Client;
use PHPUnit\Framework\TestCase;

class PostcodesTest extends TestCase
{
/** @var Postcodes */
private $postcodes;

protected function setUp()
{
$client = new Client();
$baseUri = 'http://api.postcodes.io/postcodes/';

$this->postcodes = new Postcodes($client, $baseUri);
}

protected function tearDown()
{
$this->postcodes = null;
}

public function testShouldThrowExceptionForEmptyPostcodeArgument()
{
$this->expectException(PostcodesException::class);
$this->expectExceptionMessage('Postcode is required.');
$this->expectExceptionCode(400);

$this->postcodes->getData('');
}

public function testShouldThrowExceptionForInvalidPostcodeArgument()
{
$postcode = 'INVALID';

$this->expectException(PostcodesException::class);
$this->expectExceptionMessage(sprintf('Failed to get postcode data for "%s".', $postcode));
$this->expectExceptionCode(400);

$this->postcodes->getData($postcode);
}

public function testShouldReturnPostcodeData()
{
$expected = file_get_contents(__DIR__.'/Mock/Postcodes/response-body.txt');

$result = $this->postcodes->getData('REAL POSTCODE');

$this->assertEquals($expected, $result);
}
}

#tests/Application/Util/Mock/Postcodes/response-body.txt

Content of this file is exactly the same as Real API response I added above.

Test


$ vendor/bin/phpunit --filter PostcodesTest tests/Application/Util/PostcodesTest.php
PHPUnit 5.7.22 by Sebastian Bergmann and contributors.

... 3 / 3 (100%)

Time: 97 ms, Memory: 4.25MB

OK (3 tests, 5 assertions)

Taklitli test


Daha fazla bilgi için Testing Guzzle Clients sayfasını ziyaret edin.


namespace tests\Application\Util;

use Application\Exception\PostcodesException;
use Application\Util\Postcodes;
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\TestCase;

class PostcodesTest extends TestCase
{
public function testShouldThrowExceptionForEmptyPostcodeArgument()
{
$this->expectException(PostcodesException::class);
$this->expectExceptionMessage('Postcode is required.');
$this->expectExceptionCode(400);

$postcodes = $this->getPostcodes(400);

$postcodes->getData('');
}

public function testShouldThrowExceptionForInvalidPostcodeArgument()
{
$postcode = 'INVALID';

$this->expectException(PostcodesException::class);
$this->expectExceptionMessage(sprintf('Failed to get postcode data for "%s".', $postcode));
$this->expectExceptionCode(400);

$postcodes = $this->getPostcodes(400);

$postcodes->getData($postcode);
}

public function testShouldReturnPostcodeData()
{
$body = file_get_contents(__DIR__.'/Mock/Postcodes/response-body.txt');

$postcodes = $this->getPostcodes(200, $body);

$result = $postcodes->getData('XYZ XYZ');

$this->assertEquals($body, $result);
}

private function getPostcodes($status, $body = null)
{
$mock = new MockHandler([new Response($status, [], $body)]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);

return new Postcodes($client, 'http://mocked.postcodes.xyz/');
}
}

#tests/Application/Util/Mock/Postcodes/response-body.txt

{
"status": 200,
"result": {
"postcode": "XYZ XYZ",
"longitude": -0.000000,
"latitude": 1.111111
}
}

Test


$ vendor/bin/phpunit --filter PostcodesTest tests/Application/Util/PostcodesTest.php
PHPUnit 5.7.22 by Sebastian Bergmann and contributors.

... 3 / 3 (100%)

Time: 97 ms, Memory: 4.25MB

OK (3 tests, 5 assertions)