Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Simular el cliente Http de Symfony

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Tener la capacidad de simular objetos en las pruebas es súper impresionante, y un poco raro y complejo al mismo tiempo. Si tenemos objetos sencillos, como Dinosaur, deberíamos evitar las líneas de código adicionales y limitarnos a instanciar un Dinosaur real para la prueba. Después de todo, es bastante fácil controlar el comportamiento de Dinosaursimplemente llamando a sus métodos reales. No es necesario el simulacro.

Pero, para objetos más complejos, como HttpClient, utilizar el cliente real... puede ser un dolor de cabeza. La regla general es utilizar simulacros para objetos complejos como los servicios... pero para los objetos simples, como los modelos o las entidades, basta con utilizar el objeto real.

Si volvemos a ver el cliente HTTP de Symfony, podemos simular tanto el cliente como la respuesta para controlar su comportamiento. Pero, como la necesidad de hacer este tipo de cosas es tan común, el Cliente HTTP de Symfony viene con algunas clases especiales que pueden hacer el mocking por nosotros. Viene con dos clases reales hechas específicamente para las pruebas: MockHttpClient y MockResponse. Utilizar el sistema de burlas de PHPUnit está bien, pero éstas existen para hacernos la vida aún más fácil.

Compruébalo: en lugar de crear un simulacro para $mockResponse, instala unMockResponse() pasando por json_encode() con un array para imitar la respuesta de la API de GitHub. Coge la edición de Maverick que aparece a continuación y pégala en el array. ComoMockResponse ya está configurado, elimina los bits de $mockResponse que aparecen a continuación.

... lines 1 - 8
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
... lines 11 - 13
class GithubServiceTest extends TestCase
{
... lines 16 - 63
public function testExceptionThrownWithUnknownLabel(): void
{
$mockResponse = new MockResponse(json_encode([
[
'title' => 'Maverick',
'labels' => [['name' => 'Status: Drowsy']],
],
]));
... lines 72 - 79
}
}

Para el cliente, elimina $mockHttpClient y abajo, instala un nuevoMockHttpClient() pasando en su lugar $mockResponse. Como no vamos a hacer nada con $mockLogger, corta createMock(), elimina la variable y pégala como argumento a GithubService().

... lines 1 - 8
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
... lines 11 - 13
class GithubServiceTest extends TestCase
{
... lines 16 - 63
public function testExceptionThrownWithUnknownLabel(): void
{
$mockResponse = new MockResponse(json_encode([
[
'title' => 'Maverick',
'labels' => [['name' => 'Status: Drowsy']],
],
]));
$mockHttpClient = new MockHttpClient($mockResponse);
$service = new GithubService($mockHttpClient, $this->createMock(LoggerInterface::class));
... lines 75 - 79
}
}

Vaya, ¡esto ya tiene mejor pinta! Pero, veamos qué ocurre cuando ejecutamos las pruebas:

./vendor/bin/phpunit

Y... ¡Woah! ¡Todas las pruebas se superan!

Pero, el recuento de aserciones bajó a "16" porque MockHttpClient y MockResponseno realizan realmente ninguna aserción, como cuántas veces se llama a un método.

Entonces... ¿cuál es el beneficio real de utilizar estas clases simuladas? ¿Por qué no crear las nuestras a través de PHPUnit? Ja... Echa un vistazo a este diff de GithubService. Hemos eliminado 11 líneas de código utilizando los mocks "incorporados" en una sola prueba. Imagina cuántas líneas de código podríamos eliminar usándolas en todas nuestras pruebas. Hm... Creo que eso es exactamente lo que haremos a continuación.

Leave a comment!

0
Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=8.1.0",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "symfony/asset": "6.1.*", // v6.1.0
        "symfony/console": "6.1.*", // v6.1.4
        "symfony/dotenv": "6.1.*", // v6.1.0
        "symfony/flex": "^2", // v2.2.3
        "symfony/framework-bundle": "6.1.*", // v6.1.4
        "symfony/http-client": "6.1.*", // v6.1.4
        "symfony/runtime": "6.1.*", // v6.1.3
        "symfony/twig-bundle": "6.1.*", // v6.1.1
        "symfony/yaml": "6.1.*" // v6.1.4
    },
    "require-dev": {
        "phpunit/phpunit": "^9.5", // 9.5.23
        "symfony/browser-kit": "6.1.*", // v6.1.3
        "symfony/css-selector": "6.1.*", // v6.1.3
        "symfony/phpunit-bridge": "^6.1" // v6.1.3
    }
}
userVoice