Photo by Unsplash

Laravel Facades y Mockery: Creando tests de métodos encadenados

🤔 ¿Cómo sucedió?

Estaba intentando probar Laravel con PHPUnit. Y necesitaba probar los Facades de Laravel, y sobre todo, era un método encadenado.
1
<?php
2
3
namespace App\Http\Controllers;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Facades\Storage;
7
8
class ChainController extends Controller
9
{
10
public function index(Request $request)
11
{
12
Storage::disk('local')->put('/imagenes/contenido', $request->file('demo'));
13
14
return response()->json(['exito' => true]);
15
}
16
}
Después de esto, mis tests estaban fallando, debido a que no podía ejecutar put en null. Eso significaba, por algún motivo, que disk estaba retornando null, lo cual no era verdad.

🔨 Solución

Después de una búsqueda. Encontré en la documentación de Mockery, usado por Laravel para hacer los mocks. En la siguiente línea si no especificas el retorno, devolverá null por defecto. Y causará que los assertions fallen.
1
<?php
2
3
Storage::disk('s3')->delete('/imagenes/contenido/demo.png');
La solución para esto viene desde un simple método de Mockery andReturnSelf . Nota que esto depende de la implementación de la clase, pero la mayoría de métodos encadenados retornarán la clase donde fueron implementados. Del mismo modo, puedes usar andReturn y escribir el objeto, cadena, arreglo o estructura de datos que el Mock retornará.
Para este caso específico, necesitaba andReturnSelf . Veamos como el resultado final funciona. Para probarlo, mi ChainController está conectado a la ruta POST /chain .
1
<?php
2
3
namespace Tests\Feature;
4
5
use Illuminate\Http\UploadedFile;
6
use Illuminate\Support\Facades\Storage;
7
use Tests\TestCase;
8
9
class ChainControllerTest extends TestCase
10
{
11
public function test_using_facades()
12
{
13
Storage::fake('local');
14
15
Storage::shouldReceive('disk')->once()->with('local')->andReturnSelf();
16
Storage::shouldReceive('put')->once()->withSomeOfArgs('/imagenes/contenido');
17
18
$response = $this->post('/chain', ['demo' => UploadedFile::fake()->image('hello.jpeg')]);
19
$response->assertStatus(200);
20
}
21
}

🔗 Enlaces

Puedes ver un ejemplo funcionando, clic aquí.
Mis posts no son generados por la IA, sin embargo, podrían estar corregidos por ella. El primer borrador siempre es de mi creación

Autor

Escrito por Helmer Davila