Bu örneğimizde Behat ile test ortamında Guzzle client taklidini kullanacağız. Bunun nedeni ise, harici API'leri kullanmak istemememizdir.


Çalışma prensibi


Uygulamamızı kullandığımız zaman, dev ve prod ortamlarında AppBundle\Util\ClientHelper class kullanılır ama test ortamında ise AppBundle\Features\Mock\ClientHelperMock class kullanılır.


Config.yml


parameters:
client_helper_class: AppBundle\Util\ClientHelper

Config_test.yml


parameters:
client_helper_class: AppBundle\Features\Mock\ClientHelperMock

PostcodeService


namespace AppBundle\Service;

use AppBundle\Util\ClientHelper;
use Symfony\Component\HttpFoundation\Request;

class PostcodeService
{
private $client;
private $apiUri;

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

public function get($postcode)
{
return $this->client->request(Request::METHOD_GET, $this->apiUri.$postcode);
}
}

service:
app.service.postcode:
class: AppBundle\Service\PostcodeService
arguments:
- "@app.util.client_helper"
- "%postcodes_api%"

ClientHelper


namespace AppBundle\Util;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Stream;

class ClientHelper
{
private $client;

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

public function request($method, $uri, array $options = [])
{
$details = null;

try {
/** @var Response $response */
$response = $this->client->request($method, $uri, $options);
/** @var Stream $body */
$body = $response->getBody();
$details = $body->getContents();
} catch (ClientException $e) {
}

return $details;
}
}

services:
app.util.client_helper:
class: '%client_helper_class%'
arguments:
- '@app.util.guzzle'

app.util.guzzle:
class: GuzzleHttp\Client

ClientHelperMock


namespace AppBundle\Features\Mock;

use AppBundle\Util\ClientHelper;

class ClientHelperMock extends ClientHelper
{
public static $data;

public function request($method, $uri, array $options = [])
{
$response = [];

$position = strrpos($uri, '/');
if ($position !== false) {
$postcode = substr($uri, $position+1);

if (isset(self::$data['postcode']) && self::$data['postcode'] == $postcode) {
$response = self::$data['result'];
}
}

return json_encode($response);
}
}

Gherkin adım tanımı


/**
* @param PyStringNode $stringNode
*
* @Given /^the Postcode API is available with data:$/
*/
public function thePostcodeApiIsAvailableWith(PyStringNode $stringNode)
{
ClientHelperMock::$data = json_decode($stringNode->getRaw(), true);
}

Senaryolar


Feature: Getting postcode details.
In order to get postcode details
As a user
I should be able call call external API

Scenario: I get empty result for non-existent postcode.
Given the Postcode API is available with data:
"""
{"postcode":"POSTCODE 1","result":{"longitude":-0.11111111,"latitude":0.11111111}}
"""
When I send a "GET" request to "/postcodes/NON-EXISTENT POSTCODE"
Then the response status code should be 200
And the response should contain json:
"""
[]
"""

Scenario: I get full result for existent postcode.
Given the Postcode API is available with data:
"""
{"postcode":"POSTCODE 1","result":{"longitude":-0.11111111,"latitude":0.11111111}}
"""
When I send a "GET" request to "/postcodes/POSTCODE 1"
Then the response status code should be 200
And the response should contain json:
"""
{"longitude":-0.11111111,"latitude":0.11111111}
"""

Sonuç


$ vendor/bin/behat --suite=app src/AppBundle/Features/Postcode.feature
Feature: Getting postcode details.
In order to get postcode details
As a user
I should be able call call external API

Scenario: I get empty result for non-existent postcode.
Given the Postcode API is available with data:
"""
{"postcode":"POSTCODE 1","result":{"longitude":-0.11111111,"latitude":0.11111111}}
"""
When I send a "GET" request to "/postcodes/NON-EXISTENT POSTCODE"
Then the response status code should be 200
And the response should contain json:
"""
[]
"""

Scenario: I get full result for existent postcode.
Given the Postcode API is available with data:
"""
{"postcode":"POSTCODE 1","result":{"longitude":-0.11111111,"latitude":0.11111111}}
"""
When I send a "GET" request to "/postcodes/POSTCODE 1"
Then the response status code should be 200
And the response should contain json:
"""
{"longitude":-0.11111111,"latitude":0.11111111}
"""

2 scenarios (2 passed)
8 steps (8 passed)
0m1.24s (30.72Mb)