Testing Guzzle Clients

Guzzle fornece várias ferramentas que lhe permitirão gozar facilmente a camada HTTP sem necessidade de enviar pedidos através da Internet.

  • Manipulador de escárnio
  • História middleware
  • Servidor web Node.js para testes de integração

Mock Handler

Ao testar clientes HTTP, é frequentemente necessário simular cenários específicos como devolução de uma resposta bem sucedida, devolução de um erro, ou devolução específica respostas numa determinada ordem. Porque os testes unitários precisam de ser previsíveis, fáceis para apanhar, e rapidamente, acertar num verdadeiro API remoto é um cheiro de teste.

O Guzzle fornece um manipulador de zombaria que pode ser utilizado para satisfazer pedidos HTTP com uma resposta ou excepção, deslocando valores de retorno para fora de uma fila.

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

Quando não há mais respostas na fila e um pedido é enviado, um OutOfBoundsException é atirado.

História Middleware

Ao usar coisas como Mock handler, muitas vezes é necessário saber se o Os pedidos que esperava enviar foram enviados exactamente como pretendia. Enquanto o mock o manipulador responde com respostas zombadas, o middleware da história mantém um histórico dos pedidos que foram enviados por um cliente.

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.
}

Test Web Server

A utilização de respostas simuladas é quase sempre suficiente quando se testa um cliente de serviço web. Ao implementar HTTP handlers, você irá necessitam de enviar pedidos HTTP reais, a fim de testar suficientemente o manipulador. Contudo, uma melhor prática é contactar um servidor web local em vez de um servidor através da Internet.

  • Os testes são mais fiáveis
  • Os testes não requerem uma ligação em rede
  • Os testes não têm dependências externas

Usando o servidor de testes

Advertência

A seguinte funcionalidade é fornecida para ajudar os criadores do Guzzle desenvolver manipuladores HTTP. Não há promessa de compatibilidade inversa quando se trata do servidor de testes node.js ou do GuzzleHttp\Tests\Server classe. Se estiver a utilizar o servidor de teste ou a classe Server class outside of guzzlehttp/guzzle, depois terá de configurar o auto-carregamento e assegurar que o servidor web é iniciado manualmente.

Dica

Quase nunca é necessário utilizar este servidor web de teste. Só deverá alguma vez considerar a sua utilização no desenvolvimento de manipuladores HTTP. O servidor web de teste não é necessário para pedidos de troça. Para isso, por favor utilize o Manipulador de escárnio e middleware de história.

Guzzle envia com um servidor de testes node.js que recebe pedidos e devolve respostas de uma fila de espera. O servidor de testes expõe uma API simples que é utilizada para inquirir respostas e inspeccionar os pedidos que tenha recebido.

Qualquer operação no objecto Server irá assegurar que o servidor esteja a funcionar e aguarde até poder receber pedidos antes de regresso.

GuzzleHttp\Tests\Server fornece uma interface estática para o servidor de testes. Você pode enfileirar uma resposta HTTP ou um conjunto de respostas, chamando Server::enqueue(). Este método aceita um conjunto de Psr\Http\Message\ResponseInterface e Excepção objectos.

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

Quando uma resposta é enfileirada no servidor de teste, o servidor de teste irá remover qualquer respostas previamente enfileiradas. À medida que o servidor recebe pedidos, as respostas enfileiradas são desfilhados e devolvidos ao pedido. Quando a fila está vazia, o servidor irá devolver uma resposta de 500.

Pode inspeccionar os pedidos que o servidor recuperou chamando Server::received().

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

Pode limpar a lista de pedidos recebidos do servidor web usando o método Server::flush().

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