22/10/2017 - PHPUNIT
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.
{
"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"
}
}
}
namespace Application\Exception;
use Exception;
class PostcodesException extends Exception
{
public function __construct($message, $code = 400)
{
parent::__construct($message, $code);
}
}
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);
}
}
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.
$ 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)
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
}
}
$ 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)