Symfony 2.3, el libro oficial

10.4. Trabajando con el cliente de los tests

El cliente utilizado en los tests simula ser un cliente HTTP (algo parecido a un navegador de usuario) y sirve para realizar peticiones a tu aplicación Symfony2:

$crawler = $client->request('GET', '/hello/Fabien');

El método request() toma como argumentos el método HTTP y una URL y devuelve como resultado una instancia de Crawler.

Truco Una buena práctica para los tests funcionales consiste en escribir a mano las URLs accedidas por el cliente en vez de generarlas automáticamente con el sistema de enrutamiento de Symfony. De lo contrario, si cambias una URL sin querer, los tests no detectarán ningún problema pero habrás roto la aplicación para los usuarios que acceden a tu sitio web.

Utiliza este objeto Crawler para encontrar elementos específicos en la respuesta. Después puedes utilizar estos elementos para pinchar en los enlaces y para enviar formularios:

$link = $crawler->selectLink('Go elsewhere...')->link();
$crawler = $client->click($link);

$form = $crawler->selectButton('validate')->form();
$crawler = $client->submit($form, array('name' => 'Fabien'));

Los métodos click() y submit() devuelven un objeto de tipo Crawler. Estos métodos son la mejor manera de navegar por tu aplicación, ya que se encargan de un montón de tareas necesarias, como detectar el método HTTP de un formulario y te proporciona una buena API para subir archivos.

Truco Aprenderás más sobre los objetos Link y Form más adelante en la sección dedicada al Crawler.

También puedes usar el método request() para simular directamente el envío de formularios o para realizar peticiones más complejas:

// envía un formulario directamente (¡es más fácil usar el 'Crawler'!)
$client->request('POST', '/submit', array('name' => 'Fabien'));

// Enviar directamente una cadena de texto en formato JSON
$client->request(
    'POST',
    '/submit',
    array(),
    array(),
    array('CONTENT_TYPE' => 'application/json'),
    '{"name":"Fabien"}'
);

// envía un formulario (y sube un archivo en el propio formulario)
use Symfony\Component\HttpFoundation\File\UploadedFile;

$photo = new UploadedFile(
    '/path/to/photo.jpg',
    'photo.jpg',
    'image/jpeg',
    123
);

$client->request(
    'POST',
    '/submit',
    array('name' => 'Fabien'),
    array('photo' => $photo)
);

// Realiza una petición DELETE y establece varias cabeceras HTTP
$client->request(
    'DELETE',
    '/post/12',
    array(),
    array(),
    array('PHP_AUTH_USER' => 'username', 'PHP_AUTH_PW' => 'pa$$word')
);

Por último, también puedes hacer que cada petición se ejecute en su propio proceso PHP independiente para evitar efectos secundarios cuando se trabaja con varios clientes en el mismo test:

$client->insulate();

El cliente soporta la mayoría de operaciones que se pueden hacer en un navegador real:

$client->back();
$client->forward();
$client->reload();

// Limpia todas las cookies y el historial
$client->restart();

10.4.2. Accediendo a los objetos internos

Cuando se utiliza el cliente en los tests de la aplicación, resulta habitual querar acceder a los objetos internos del cliente, como su historial o sus cookies:

$history   = $client->getHistory();
$cookieJar = $client->getCookieJar();

También puedes obtener los objetos relacionados con la última petición. Los métodos getInternalRequest() y getInternalResponse() están disponibles a partir de la versión 2.3 de Symfony:

// obtiene la instancia de la petición HttpKernel
$request  = $client->getRequest();

// obtiene la instancia de la petición BrowserKit
$request  = $client->getInternalRequest();

// obtiene la instancia de la respuesta HttpKernel
$response = $client->getResponse();

// obtiene la instancia de la respuesta BrowserKit
$response = $client->getInternalResponse();

$crawler  = $client->getCrawler();

Si tus peticiones no son aisladas (no utilizas $client->insulate();), también puedes acceder al contenedor de inyección de dependencias de Symfony2 y al kernel o núcleo de tu aplicación:

$container = $client->getContainer();
$kernel    = $client->getKernel();

10.4.3. Accediendo al contenedor

Se recomienda que los tests funcionales sólo prueben la respuesta del servidor. Sin embargo, bajo ciertas circunstancias muy especiales, puede ser necesario acceder a algunos objetos internos del propio Symfony. En tales casos, puedes acceder al contenedor de inyección de dependencias con el siguiente código:

$container = $client->getContainer();

Ten en cuenta que el código anterior no funciona si utilizas un cliente asilado ($client->insulate();) o si utilizas una capa HTTP. Para listar todos los servicios disponibles en tu aplicación, ejecuta el comando container:debug de la consola.

Truco Si la información que necesitas comprobar está disponible a través del profiler de Symfony, utilízalo en lugar del contenedor.

10.4.4.  Accediendo a los datos del profiler

En cada petición, puedes habilitar el profiler de Symfony para recolectar toda la información sobre la ejecución interna de esa petición. Después, puedes utilizar esa información del profiler para asegurar por ejemplo que una determinada página requiere menos consultas a la base de datos que las indicadas.

Para obtener el profiler de la última petición, utiliza el siguiente código:

// activa el profiler para la próxima petición
$client->enableProfiler();

$crawler = $client->request('GET', '/profiler');

// obtiene el profiler
$profile = $client->getProfile();

10.4.5. Redirecciones

Cuando una petición devuelve una respuesta de tipo redirección, el cliente no la sigue automáticamente. Así puedes examinar la respuesta recibida y forzar después la redirección con el método followRedirect():

$crawler = $client->followRedirect();

Si quieres que el cliente siga todas las redirecciones automáticamente, utiliza el método followRedirects():

$client->followRedirects();