Al momento de hacer la validación con assertExist(), me genero error, la forma como lo solucione fue:
$this->assertTrue(Storage::disk('local')->exists($imageRoute));
Verificar que la carga de archivos funciona correctamente antes de construir la interfaz es una práctica que distingue a los desarrolladores que aplican TDD (Test Driven Development). En Laravel, esto es posible gracias a herramientas integradas que permiten simular archivos y discos de almacenamiento sin tocar el sistema real.
¿Cómo crear un test de carga de imágenes en Laravel?
El punto de partida es generar un archivo de prueba con el comando php artisan make:test ProfileTest [00:18]. Este comando crea una clase dentro de la carpeta de tests donde se define el comportamiento esperado. En este caso, el método se llama carga y su propósito es comprobar que una imagen se sube correctamente al servidor.
Para lograrlo se importan dos clases fundamentales:
Illuminate\Http\UploadedFile: permite crear archivos ficticios que simulan una imagen real [01:06].Illuminate\Support\Facades\Storage: da acceso al sistema de archivos y permite trabajar con discos falsos [01:18].La clase UploadedFile expone el método fake(), que genera un archivo simulado. En el ejemplo se crea una imagen llamada photo.png [02:10]. Por otro lado, Storage::fake() configura un disco de almacenamiento temporal que no afecta el entorno real del proyecto [01:50].
¿Qué afirmaciones se utilizan dentro del test?
Dentro del test se realizan dos verificaciones clave:
profiles del disco configurado [02:40]. Se accede al nombre del archivo mediante $foto->hashName(), que devuelve el nombre generado automáticamente por Laravel.profile mediante una petición GET [03:08].El método $this->post() simula el envío de un formulario con el archivo adjunto, sin necesidad de crear una vista ni abrir el navegador [01:57]. Esto es precisamente lo valioso del testing: probar la lógica de forma aislada.
¿Cómo programar la funcionalidad que hace pasar el test?
Al ejecutar el test por primera vez, falla [03:25]. Esto es esperado porque aún no existe la ruta ni el código que procese la carga. El flujo de TDD dicta que primero se escribe lo que se espera y después se desarrolla la funcionalidad.
La configuración de rutas requiere dos entradas en el archivo web.php:
/profile que retorna una vista [03:50]./profile que recibe el request y ejecuta la carga [04:05].php Route::get('profile', function () { return view('profile'); });
Route::post('profile', function (Illuminate\Http\Request $request) { $request->file('foto')->store('profiles'); return redirect('profile'); });
El método store('profiles') del objeto archivo se encarga de guardar la imagen dentro de la carpeta profiles del disco local [04:30]. Después, redirect('profile') envía al usuario de vuelta a la vista del perfil.
¿Dónde se almacenan los archivos durante el testing?
Cuando el test se ejecuta con Storage::fake('local'), Laravel crea una estructura temporal dentro de storage/framework/testing/disks/local/profiles [05:10]. Cada ejecución genera una nueva imagen ficticia en esa ubicación, lo que permite verificar visualmente que el proceso funciona.
Es importante distinguir entre el disco real y el disco fake. El disco falso existe solo durante la prueba y evita contaminar el almacenamiento del proyecto con archivos de prueba.
¿Por qué escribir el test antes del código?
Esta práctica garantiza que cada funcionalidad nueva tenga cobertura de pruebas desde el inicio. Al ver que el test falla primero y luego pasa tras implementar el código [05:02], se obtiene confianza de que la lógica cumple exactamente con lo definido. No se trata solo de verificar que "algo funcione", sino de documentar el comportamiento esperado del sistema.
La vista profile.blade.php se crea vacía inicialmente [04:48] para que el test pase sin errores. La construcción del formulario HTML y la experiencia visual en el navegador se desarrollan en un paso posterior, separando la lógica de negocio de la presentación.
¿Has implementado testing para la carga de archivos en tus proyectos? Comparte tu experiencia o dudas en los comentarios.
Verificar que la carga de archivos funciona correctamente antes de construir la interfaz es una práctica que distingue a los desarrolladores que aplican TDD (Test Driven Development). En Laravel, esto es posible gracias a herramientas integradas que permiten simular archivos y discos de almacenamiento sin tocar el sistema real.
El punto de partida es generar un archivo de prueba con el comando php artisan make:test ProfileTest [00:18]. Este comando crea una clase dentro de la carpeta de tests donde se define el comportamiento esperado. En este caso, el método se llama carga y su propósito es comprobar que una imagen se sube correctamente al servidor.
Para lograrlo se importan dos clases fundamentales:
Illuminate\Http\UploadedFile: permite crear archivos ficticios que simulan una imagen real [01:06].Illuminate\Support\Facades\Storage: da acceso al sistema de archivos y permite trabajar con discos falsos [01:18].La clase UploadedFile expone el método fake(), que genera un archivo simulado. En el ejemplo se crea una imagen llamada photo.png [02:10]. Por otro lado, Storage::fake() configura un disco de almacenamiento temporal que no afecta el entorno real del proyecto [01:50].
Dentro del test se realizan dos verificaciones clave:
profiles del disco configurado [02:40]. Se accede al nombre del archivo mediante $foto->hashName(), que devuelve el nombre generado automáticamente por Laravel.profile mediante una petición GET [03:08].El método $this->post() simula el envío de un formulario con el archivo adjunto, sin necesidad de crear una vista ni abrir el navegador [01:57]. Esto es precisamente lo valioso del testing: probar la lógica de forma aislada.
Al ejecutar el test por primera vez, falla [03:25]. Esto es esperado porque aún no existe la ruta ni el código que procese la carga. El flujo de TDD dicta que primero se escribe lo que se espera y después se desarrolla la funcionalidad.
La configuración de rutas requiere dos entradas en el archivo web.php:
/profile que retorna una vista [03:50]./profile que recibe el request y ejecuta la carga [04:05].php Route::get('profile', function () { return view('profile'); });
Route::post('profile', function (Illuminate\Http\Request $request) { $request->file('foto')->store('profiles'); return redirect('profile'); });
El método store('profiles') del objeto archivo se encarga de guardar la imagen dentro de la carpeta profiles del disco local [04:30]. Después, redirect('profile') envía al usuario de vuelta a la vista del perfil.
Cuando el test se ejecuta con Storage::fake('local'), Laravel crea una estructura temporal dentro de storage/framework/testing/disks/local/profiles [05:10]. Cada ejecución genera una nueva imagen ficticia en esa ubicación, lo que permite verificar visualmente que el proceso funciona.
Es importante distinguir entre el disco real y el disco fake. El disco falso existe solo durante la prueba y evita contaminar el almacenamiento del proyecto con archivos de prueba.
Esta práctica garantiza que cada funcionalidad nueva tenga cobertura de pruebas desde el inicio. Al ver que el test falla primero y luego pasa tras implementar el código [05:02], se obtiene confianza de que la lógica cumple exactamente con lo definido. No se trata solo de verificar que "algo funcione", sino de documentar el comportamiento esperado del sistema.
La vista profile.blade.php se crea vacía inicialmente [04:48] para que el test pase sin errores. La construcción del formulario HTML y la experiencia visual en el navegador se desarrollan en un paso posterior, separando la lógica de negocio de la presentación.
¿Has implementado testing para la carga de archivos en tus proyectos? Comparte tu experiencia o dudas en los comentarios.
Al momento de hacer la validación con assertExist(), me genero error, la forma como lo solucione fue:
$this->assertTrue(Storage::disk('local')->exists($imageRoute));
He notado que en varias clases el profe a veces declara las funciones de los tests con camel case y en otras con snake case. Opino a mi criterio que lo mejor es siempre estandarizar la codificación. Es decir, si por ejemplo declaro mis funciones de testing en un archivo con camel case, entonces debo seguir ese mismo estandar para que así el código luzca siempre prolijo y ordenado :D
Mi linter se estaba quejando del código del profesor porque $request->file('photo'); puede regresar null y por lo tanto generaría el famoso 'null pointer exception'... lo solucioné así aprovechando el nuevo feature de php 8 'null safe operator'
Route::post(
'profile',
function (\Illuminate\Http\Request $request) {
$file = $request->file('photo');
$file?->store('profiles');
return redirect('profile');
}
);
Estuve dándole muchas vueltas y no me funcionaba la validación del ProfileTest. siempre me retornaba un error relacionado a no encontraba la ruta o el directorio, porque nunca ingresaba al ruta de Profilepara guardar la imagen, indagando mas me saltaba otro error y me retornaba el código "419"
El error de código "" esta relacionado con la expiración del token de seguridad cuando no se usa CSRF, la solución que encontré fue añadir este código al inicio de la validación.
$this->withoutMiddleware();
PD: otra forma que puedes usar para hacer el "Assert" y comprobar si existe la imagen es :
$exists = Storage::disk('local')->exists("profiles/{$photo->hashName()}");
$this->assertTrue($exists);
espero que le ayude a alguien.
Me están gustando estas clase y hasta cierto punto entiendo los pasos que ejecuta el profe, pero aún no alcanzo a contextualizarlo en un proyecto real.
Asegurense de tener la extension GD en php activada para que el codigo funcione correctamente
Uhhhmm, me pregunto cómo se haría este test en un sistema distribuido, por ejemplo, subir algo a S3, imagino que sería algo del tipo, hacerle fake al disco "s3", podría ser eso, o realmente subir el archivo y testear que sí s sube y luego eliminarlo para que los tests no consuman almacenamiento dentro de S3 🤔
Para versiones recientes de Laravel la ruta es:
use App\Http\Controllers\ProfileController;
Route::post('/profile', [ProfileController::class, 'upload']);
Estoy usando Laravel 8.78.1 con PHP 7.4.27 y me indica que el método assertExists() no existe. Alguien más tiene este problema?
Para los que esten usando Laravel 11 esta es la forma de hacer el assert
$this->assertTrue(Storage::disk('local')->exists("profiles/{$photo->hashName()}"));