Mocking – Documentación de Laravel 6

Introducción

Al momento de probar aplicaciones de Laravel, puedes querer «simular» (mock) ciertos aspectos de tu aplicación de modo que realmente no sean ejecutados durante una prueba dada. Por ejemplo, al momento de probar un controlador que despacha un evento, puedes querer simular los listeners de eventos de modo que realmente no se ejecuten durante la prueba. Esto te permite probar solamente la respuesta HTTP del controlador sin preocuparte por la ejecución de los listeners de eventos, ya que los listeners de eventos pueden ser evaluados en sus propios casos de prueba.

Laravel provee funciones helpers para simular eventos, tareas y clases facades predeterminadas. Estos helpers proporcionan principalmente una capa conveniente sobre la clase Mockery de modo que no tengas que hacer manualmente llamadas complicadas a métodos Mockery. Puedes también usar Mockery o PHPUnit para crear tus propios mocks o spies.

Mocking de objetos

Cuando hagas mocking de un objeto que vas a inyectar en tu aplicación a través del contenedor de servicio de Laravel, debes enlazar tu instancia a la que le has hecho mocking al contenedor como un enlace de instance. Esto le indicará al contenedor que use tu instancia «mockeada» del objeto en lugar de construir el propio objeto:

use App\Service;
use Mockery;

$this->instance(Service::class, Mockery::mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
}));

Para hacer esto más conveniente, puedes usar el método mock, que es proporcionado por la clase TestCase base de Laravel:

use App\Service;

$this->mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
});

Puedes usar el método partialMock cuando sólo necesitas simular algunos métodos de un objeto. Los métodos que no son simulados serán ejecutados de forma normal al ser llamados:

use App\Service;

$this->partialMock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
});

De forma similar, si quieres espiar un objeto, la clase de prueba base de Laravel ofrece un método spy como un wrapper conveniente del método Mockery::spy:

use App\Service;

$this->spy(Service::class, function ($mock) {
    $mock->shouldHaveReceived('process');
});

Fake de trabajos (jobs)

Como una alternativa a mocking, puedes usar el método fake de la clase facade Bus para evitar que determinadas tareas sean despachadas. Al momento de usar fakes, las aserciones serán hechas después de que el código bajo prueba sea ejecutado.

<?php

namespace Tests\Feature;

use App\Jobs\ShipOrder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Bus;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testOrderShipping()
    {
        Bus::fake();

        // Perform order shipping...

        Bus::assertDispatched(ShipOrder::class, function ($job) use ($order) {
            return $job->order->id === $order->id;
        });

        // Assert a job was not dispatched...
        Bus::assertNotDispatched(AnotherJob::class);
    }
}

Fake de eventos

Como una alternativa a mocking, puedes usar el método fake de la clase facade Event para prevenir la ejecución de todos los listeners de eventos. Después puedes comprobar que los eventos fueron despachados e incluso inspeccionar los datos que recibieron. Al momento de usar fakes, las aserciones son hechas después de que el código bajo prueba sea ejecutado:

<?php

namespace Tests\Feature;

use App\Events\OrderFailedToShip;
use App\Events\OrderShipped;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
    * Test order shipping.
    */
    public function testOrderShipping()
    {
        Event::fake();

        // Perform order shipping...

        Event::assertDispatched(OrderShipped::class, function ($e) use ($order) {
            return $e->order->id === $order->id;
        });

        // Assert an event was dispatched twice...
        Event::assertDispatched(OrderShipped::class, 2);

        // Assert an event was not dispatched...
        Event::assertNotDispatched(OrderFailedToShip::class);
    }
}

Después de llamar a Event::fake(), no se ejecutarán listeners de eventos. Entonces, si tus pruebas usan model factories que dependen de eventos, como crear una UUID durante el evento de modelo creating, debes llamar Event::fake() después de usar tus factories.

Haciendo fake a un subconjunto de eventos

Si sólo deseas hacer fake a listeners de eventos para un grupo específico de eventos, puedes pasarlos a los métodos fake o fakeFor:

/**
* Test order process.
*/
public function testOrderProcess()
{
    Event::fake([
        OrderCreated::class,
    ]);

    $order = factory(Order::class)->create();

    Event::assertDispatched(OrderCreated::class);

    // Other events are dispatched as normal...
    $order->update([...]);
}

Ver post

Pruebas de Base de Datos – Documentación de Laravel 6

Introducción

Laravel proporciona una variedad de herramientas útiles para hacer que sea más fácil probar tus aplicaciones que manejan base de datos. Primero, puedes usar el método (helper) assertDatabaseHas para comprobar que los datos existentes en la base de datos coinciden con un conjunto dado de criterios. Por ejemplo, si quisieras verificar que hay un registro en la tabla users con el valor email de [email protected], puedes hacer lo siguiente:

public function testDatabase()
{
    // Make call to application...

    $this->assertDatabaseHas('users', [
        'email' => '[email protected]',
    ]);
}

También podrías usar el método assertDatabaseMissing para comprobar que esos datos no existen en la base de datos.

El método assertDatabaseHas y otros métodos como éste son muy convenientes. Eres libre de usar cualquiera de los métodos de aserción integrados de PHPUnit para complementar tus pruebas funcionales (Feature tests).

Generando factories

Para crear un factory, usa el comando Artisan make:factory:

php artisan make:factory PostFactory

El nuevo factory será colocado en tu directorio database/factories.

La opción --model puede ser usada para indicar el nombre del modelo creado por el factory. Esta opción pre-completará el archivo de factory generado con el modelo dado:

php artisan make:factory PostFactory --model=Post

Reiniciando la base de datos después de cada prueba

Con frecuencia es útil reinicializar tu base de datos después de cada prueba de modo que los datos de una prueba previa no interfieran con las pruebas subsecuentes. El trait RefreshDatabase toma como enfoque más óptimo migrar tu base de datos de pruebas, dependiendo de si estás usando una base de datos en memoria o una base de datos tradicional. Usa el trait en tu clase de prueba y todo será manejado automáticamente sin que tengas que preocuparte por esto:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
    * A basic functional test example.
    *
    * @return void
    */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}

Escribiendo factories

Al momento de probar, puedes necesitar insertar unos cuantos registros dentro de tu base de datos antes de ejecutar tu prueba. En lugar de especificar manualmente el valor de cada columna cuando crees estos datos de prueba, Laravel permite que definas un conjunto de atributos predeterminados para cada uno de tus modelos de Eloquent usando factories de modelos. Para empezar, demos un vistazo al archivo database/factories/UserFactory.php en tu aplicación. De forma predeterminada, este archivo contiene una definición de factory:

use Faker\Generator as Faker;
use Illuminate\Support\Str;

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
        'remember_token' => Str::random(10),
    ];
});

Dentro del Closure, la cual sirve como la definición del factory, puedes devolver los valores de prueba predeterminados de todos los atributos del modelo. El Closure recibirá una instancia de la librería PHP Faker, la cual permitirá que generes convenientemente varios tipos de datos aleatorios para las pruebas.

También puedes crear archivos de factories adicionales para cada modelo para una mejor organización. Por ejemplo, podrías crear archivos UserFactory.php y CommentFactory.php dentro de tu directorio database/factories. Todos los archivos dentro del directorio factories serán cargados automáticamente por Laravel.

Puedes establecer la configuración regional de Faker agregando una opción faker_locale a tu archivo de configuración config/app.php.

Ver post

Laravel Dusk – Documentación de Laravel 6

Introducción

Laravel Dusk proporciona una API de automatización y prueba para navegador expresiva y fácil de usar. De forma predeterminada, Dusk no requiere que instales JDK o Selenium en tu computador. En su lugar, Dusk usa una instalación de ChromeDriver independiente. Sin embargo, siéntete libre de utilizar cualquier otro driver compatible con Selenium que desees.

Instalación

Para empezar, debes agregar la dependencia de Composer laravel/dusk a tu proyecto:

composer require --dev laravel/dusk

Si estás registrando manualmente el proveedor de servicio de Dusk, nunca deberías registrarlo en tu entorno de producción, ya que hacerlo así podría conducir a que usuarios arbitrarios sean capaces de autenticarse en tu aplicación.

Después de la instalación del paquete Dusk, ejecuta el comando Artisan dusk:install:

php artisan dusk:install

Un directorio Browser será creado dentro de tu directorio tests y contendrá una prueba de ejemplo. Seguido, establece la variable de entorno APP_URL en tu archivo .env. Este valor debería coincidir con la URL que uses para acceder a tu aplicación en un navegador.

Para ejecutar tus pruebas, usa el comando de Artisan dusk. El comando dusk acepta cualquier argumento que también sea aceptado por el comando phpunit:

php artisan dusk

Si tuviste fallos en las pruebas la última vez que se ejecutó el comando dusk, puedes ahorrar tiempo volviendo a ejecutar las pruebas fallidas usando el comando dusk:fails:

php artisan dusk:fails

Ver post

Pruebas de consola – Documentación de Laravel 6

Introducción

Además de simplificar las pruebas de HTTP, Laravel proporciona una API simple para probar las aplicaciones de consola que solicitan información al usuario.

Esperando entrada / salida

Laravel te permite «simular» (mock) fácilmente la entrada de datos por parte del usuario mediante la consola utilizando el método expectsQuestion. Además, puedes especificar el código de salida y el texto que esperas que genere el comando de consola utilizando los métodos assertExitCode y expectsOutput. Por ejemplo, considera el siguiente comando de consola:

Artisan::command('question', function () {
    $name = $this->ask('What is your name?');

    $language = $this->choice('Which language do you program in?', [
        'PHP',
        'Ruby',
        'Python',
    ]);

    $this->line('Your name is '.$name.' and you program in '.$language.'.');
});

Puedes probar este comando con la siguiente prueba que utiliza los métodos expectsQuestion, expectsOutput y assertExitCode:

/**
* Test a console command.
*
* @return void
*/
public function testConsoleCommand()
{
    $this->artisan('question')
         ->expectsQuestion('What is your name?', 'Taylor Otwell')
         ->expectsQuestion('Which language do you program in?', 'PHP')
         ->expectsOutput('Your name is Taylor Otwell and you program in PHP.')
         ->assertExitCode(0);
}

Pruebas HTTP – Documentación de Laravel 6

Introducción

Laravel proporciona una API muy fluida para hacer solicitudes HTTP a tu aplicación y examinar la salida. Por ejemplo, demos un vistazo a la prueba funcional definida a continuación:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
    * A basic test example.
    *
    * @return void
    */
    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}

El método get simula una solicitud GET dentro de la aplicación, mientras que el método assertStatus comprueba que la respuesta devuelta debería tener el código de estado HTTP dado. Además de esta sencilla aserción, Laravel también contiene una variedad de aserciones para inspeccionar de la respuesta los encabezados, contenidos, estructura JSON y más.

Ver post

Pruebas: Primeros Pasos – Documentación de Laravel 6

Introducción

Laravel está construido pensando en las pruebas. De hecho, el soporte para pruebas con PHPUnit es incluido de forma predeterminada y un archivo phpunit.xml ya está configurado para tu aplicación. El framework también viene con métodos de ayuda convenientes (helpers) que permiten que pruebes tus aplicaciones de forma expresiva.

De forma predeterminada, el directorio tests de tu aplicación contiene dos directorios: Feature y Unit. Las pruebas unitarias (Unit) son pruebas que se enfocan en una muy pequeña porción aislada de tu código. De hecho, la mayoría de las pruebas unitarias se enfocan probablemente en un solo método. Las pruebas funcionales (Feature) pueden probar una porción más grande de tu código, incluyendo la forma en la que varios objetos interactúan entre sí e incluso una solicitud HTTP completa para un endpoint de JSON.

Un archivo ExampleTest.php es proporcionado en ambos directorios de prueba Feature y Unit. Después de instalar una nueva aplicación de Laravel, ejecuta phpunit en la línea de comandos para ejecutar tus pruebas.

Entorno

Al momento de ejecutar las pruebas por medio de phpunit, Laravel establecerá automáticamente el entorno de configuración a testing debido a las variables de entorno definidas en el archivo phpunit.xml. Laravel también configura automáticamente la sesión y caché para que usen el manejador o driver array al momento de ejecutar las pruebas, lo que significa que ninguna sesión o caché de datos será conservada mientras las pruebas son ejecutadas.

Eres libre de definir otros valores de configuración del entorno de pruebas cuando sea necesario. Las variables de entorno testing pueden ser configuradas en el archivo phpunit.xml, pero ¡asegúrate de limpiar tu caché de configuración usando el comando Artisan config:clear antes de ejecutar tus pruebas!

Además, puedes crear un archivo .env.testing en la raíz de tu proyecto. Este archivo anulará el archivo .env cuando ejecutes las pruebas PHPUnit o cuando ejecutes los comandos de Artisan con la opción --env = testing.

Creando y ejecutando pruebas

Para crear un nuevo caso de prueba, usa el comando Artisan make:test:

// Create a test in the Feature directory...
php artisan make:test UserTest

// Create a test in the Unit directory...
php artisan make:test UserTest --unit

Una vez que la prueba ha sido generada, puedes definir métodos de pruebas como lo harías normalmente usando PHPUnit. Para ejecutar tus pruebas, ejecuta el comando phpunit desde tu terminal:

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /**
    * A basic test example.
    *
    * @return void
    */
    public function testBasicTest()
    {
        $this->assertTrue(true);
    }
}

Si defines tus propios métodos setUp / tearDown dentro de una clase de prueba, asegúrate de ejecutar los métodos parent::setUp() / parent::tearDown() respectivos en la clase padre.

Eloquent: Serialización – Documentación de Laravel 6

Introducción

Al momento de construir APIs JSON, con frecuencia necesitas convertir tus modelos y relaciones a arreglos o JSON. Eloquent incluye métodos convenientes para hacer estas conversiones, también como controlar cuáles atributos están incluidos en tus serializaciones.

Serializando modelos y colecciones

Serializando a arreglos

Para convertir un modelo y sus relaciones cargadas a un arreglo, debes usar el método toArray. Este método es recursivo, ya que todos los atributos y todas las relaciones (incluyendo las relaciones de relaciones) serán convertidas a arreglos:

$user = App\User::with('roles')->first();

return $user->toArray();

Para convertir solo los atributos de un modelo a un arreglo, usa el método attributesToArray:

$user = App\User::first();

return $user->attributesToArray();

También puedes convertir colecciones completas de modelos en arreglos:

$users = App\User::all();

return $users->toArray();

Ver post

Eloquent: Recursos API – Documentación de Laravel 6

Introducción

Al crear una API, es posible que necesites una capa de transformación que se ubique entre tus modelos Eloquent y las respuestas JSON que realmente se devuelven a los usuarios de tu aplicación. Las clases de recursos de Laravel te permiten transformar tus modelos y colecciones de modelos de forma expresiva y sencilla en JSON.

Generación de recursos

Para generar una clase de recurso, puedes usar el comando de Artisan make:resource. Por defecto, los recursos estarán localizados en el directorio app/Http/Resources de tu aplicación. Los recursos extienden de la clase Illuminate\Http\Resources\Json\JsonResource:

php artisan make:resource User

Colecciones de recursos

Además de generar recursos que transforman modelos individuales, puedes generar recursos que sean responsables de transformar colecciones de modelos. Esto permite que tu respuesta incluya enlaces y otra metainformación relevante para una colección completa de un recurso determinado.

Para crear una colección de recursos, debes utilizar la opción --collection al crear el recurso. O, incluir la palabra Collection en el nombre del recurso que le indicará a Laravel que debe crear un recurso de colección. Los recursos de colección extienden la clase Illuminate\Http\Resources\Json\ResourceCollection:

php artisan make:resource Users --collection

php artisan make:resource UserCollection

Descripción general del concepto

Esta es una explicación general de recursos y colecciones de recursos. Te recomendamos que leas las otras secciones de esta documentación para obtener una comprensión más profunda de la personalización y el poder que te ofrecen los recursos.

Antes de sumergirte en todas las opciones disponibles para escribir recursos, primero analicemos cómo se utilizan los recursos dentro de Laravel. Una clase de recurso representa un modelo único que debe transformarse en una estructura JSON. Por ejemplo, aquí hay una clase de recurso User simple:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class User extends JsonResource
{
    /**
    * Transform the resource into an array.
    *
    * @param  \Illuminate\Http\Request  $request
    * @return array
    */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

Cada clase de recurso define un método toArray que devuelve el arreglo de atributos que deben convertirse a JSON al enviar la respuesta. Observa que podemos acceder a las propiedades del modelo directamente desde la variable $this. Esto es porque la clase del recurso va a redirigir de manera automática el acceso de propiedades y métodos al modelo asignado. Una vez que se define el recurso, se puede devolver desde una ruta o controlador:

use App\Http\Resources\User as UserResource;
use App\User;

Route::get('/user', function () {
    return new UserResource(User::find(1));
});

Ver post

Eloquent: Mutators – Documentación de Laravel 6

Introducción

Los accessors y mutators permiten que des formato a los valores de atributos de Eloquent cuando los obtienes o estableces en las instancias de modelo. Por ejemplo, puede que te guste usar el encriptador de Laravel para cifrar un valor mientras es almacenado en la base de datos y después descifrar automáticamente el atributo cuando accedes a él en un modelo de Eloquent.

Además de los accessors y los mutators personalizados, Eloquent también puede convertir automáticamente campos de fecha a instancias Carbon o incluso convertir campos de texto a JSON.

Accessors y mutators

Ver post

Eloquent: Colecciones – Documentación de Laravel 6

Introducción

Todos los conjuntos de multi-resultados retornados por Eloquent son instancias del objeto Illuminate\Database\Eloquent\Collection, incluyendo los resultados obtenidos por medio del método get o accedidos por medio de una relación. El objeto de la colección Eloquent extiende la colección base de Laravel, así hereda naturalmente docenas de métodos usados para trabajar fluidamente con el arreglo subyacente de modelos de Eloquent.

Todas las colecciones también sirven como iteradores, permitiendo que iteres sobre ellas como si fueran simples arreglos de PHP:

$users = App\User::where('active', 1)->get();

foreach ($users as $user) {
    echo $user->name;
}

Sin embargo, las colecciones son mucho más poderosas que los arreglos y exponen una variedad de operaciones de mapeo / reducción que pueden ser encadenadas usando una interfaz intuitiva. Por ejemplo, vamos a remover todos los modelos inactivos y traeremos el primer nombre para cada usuario restante:

$users = App\User::all();

$names = $users->reject(function ($user) {
    return $user->active === false;
})
->map(function ($user) {
    return $user->name;
});

Mientras que la mayoría de los métodos de colección Eloquent devuelven una nueva instancia de una colección Eloquent, los métodos pluck, keys, zip, collapse, flatten y flip devuelven una instancia de colección base. De igual forma, si una operación map devuelve una colección que no contenga modelos Eloquent, será automáticamente convertida a una colección base.

Métodos Disponibles

Ver post

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

Suscríbete a nuestro boletín

Recibe consejos útiles, promos y múltiples recursos directamente en tu correo.

Tu nombre y correo serán enviados directamente a MailChimp. No compartiremos tus datos con otras empresas.