Тестване на клиенти на Guzzle

Guzzle предоставя няколко инструмента, които ви позволяват лесно да се подигравате с HTTP слоя, без да се налага да изпращате заявки по интернет.

  • Макет на манипулатор
  • Междинен софтуер за история
  • Уеб сървър Node.js за тестване на интеграцията

Mock Handler

Когато тествате HTTP клиенти, често се налага да симулирате специфични сценарии като връщане на успешен отговор, връщане на грешка или връщане на специфични отговори в определен ред. Тъй като unit тестовете трябва да са предвидими, лесни и бързи, използването на действителен отдалечен API е миризма на тест.

Guzzle предоставя приспивателен манипулатор, който може да се използва за изпълнение на HTTP заявки с отговор или изключение чрез преместване на върнатите стойности от опашка.

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\RequestException;

// Create a mock and queue two responses.
$mock = new MockHandler([
    new Response(200, ['X-Foo' => 'Bar'], 'Hello, World'),
    new Response(202, ['Content-Length' => 0]),
    new RequestException('Error Communicating with Server', new Request('GET', 'test'))
]);

$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);

// The first request is intercepted with the first response.
$response = $client->request('GET', '/');
echo $response->getStatusCode();
//> 200
echo $response->getBody();
//> Hello, World
// The second request is intercepted with the second response.
echo $client->request('GET', '/')->getStatusCode();
//> 202

// Reset the queue and queue up a new response
$mock->reset();
$mock->append(new Response(201));

// As the mock was reset, the new response is the 201 CREATED,
// instead of the previously queued RequestException
echo $client->request('GET', '/')->getStatusCode();
//> 201

Когато в опашката няма повече отговори и се изпрати заявка, се изхвърля OutOfBoundsException.

History Middleware

Когато използвате неща като Mock, често трябва да знаете дали заявките, които сте очаквали да изпратите, са били изпратени точно както сте искали. Докато mock обработващото устройство отговаря с подигравателни отговори, междинният софтуер за история поддържа историята на заявките, които са били изпратени от даден клиент.

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;

$container = [];
$history = Middleware::history($container);

$handlerStack = HandlerStack::create();
// or $handlerStack = HandlerStack::create($mock); if using the Mock handler.

// Add the history middleware to the handler stack.
$handlerStack->push($history);

$client = new Client(['handler' => $handlerStack]);

$client->request('GET', 'http://httpbin.org/get');
$client->request('HEAD', 'http://httpbin.org/get');

// Count the number of transactions
echo count($container);
//> 2

// Iterate over the requests and responses
foreach ($container as $transaction) {
    echo $transaction['request']->getMethod();
    //> GET, HEAD
    if ($transaction['response']) {
        echo $transaction['response']->getStatusCode();
        //> 200, 200
    } elseif ($transaction['error']) {
        echo $transaction['error'];
        //> exception
    }
    var_dump($transaction['options']);
    //> dumps the request options of the sent request.
}

Тестов уеб сървър

Използването на имитационни отговори почти винаги е достатъчно при тестване на клиент на уеб услуга. Когато реализирате потребителски HTTP манипулатори, ще трябва да изпратите действителни HTTP заявки, за да тествате достатъчно добре обработчика. Въпреки това най-добрата практика е да се свържете с локален уеб сървър, а не със сървър през интернет.

  • Тестовете са по-надеждни
  • Тестовете не изискват мрежова връзка
  • Тестовете нямат външни зависимости

Използване на тестовия сървър

Предупреждение

Следната функционалност е предоставена в помощ на разработчиците на Guzzle да разработват HTTP манипулатори. Не се обещава обратна съвместимост. когато става въпрос за тестовия сървър на node.js или за GuzzleHttp\Tests\Server клас. Ако използвате тестовия сървър или класа Server извън guzzlehttp/guzzle, тогава ще трябва да конфигурирате автоматично зареждане и да се уверите, че уеб сървърът се стартира ръчно.

Намек

Почти никога не се налага да използвате този тестов уеб сървър. Трябва да използвате само да го използвате, когато разработвате HTTP манипулатори. Тестовият уеб сървър не е необходим за подигравателни заявки. За тази цел използвайте Mock handler и history middleware.

Guzzle се доставя с тестови сървър node.js, който получава заявки и връща отговори от опашка. Тестовият сървър разкрива прост API, който се използва за да записва отговори и да проверява получените заявки.

Всяка операция върху обекта Server ще гарантира, че сървъра и ще изчака, докато той може да получава заявки, преди да да върне.

GuzzleHttp\Tests\Server предоставя статичен интерфейс към тестовия сървър. Можете да можете да поставите в опашка HTTP отговор или масив от отговори, като извикате Server::enqueue(). Този метод приема масив от Psr\Http\Message\ResponseInterface и Exception обекти.

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Tests\Server;

// Start the server and queue a response
Server::enqueue([
    new Response(200, ['Content-Length' => 0])
]);

$client = new Client(['base_uri' => Server::$url]);
echo $client->request('GET', '/foo')->getStatusCode();
// 200

Когато отговорът е поставен в опашката на тестовия сървър, тестовият сървър ще премахне всички предишните опашки за отговори. Когато сървърът получава заявки, подредените в опашката отговори се отстраняват от опашката и се връщат към заявката. Когато опашката е празна, сървърът ще върне отговор 500.

Можете да прегледате заявките, които сървърът е получил, като извикате Server::received().

foreach (Server::received() as $response) {
    echo $response->getStatusCode();
}

Можете да изчистите списъка на получените заявки от уеб сървъра с помощта на метода Server::flush().

Server::flush();
echo count(Server::received());
// 0