Pruebas Unitarias con Pest vs PHPUnit

De manera demostrativa. vamos a hacer juntos la traducción de la prueba para los post de php unit a pest si no la quieres ver puedes irte al final del video el último minuto o 2 minutos y ver cómo luce la prueba o directamente ir al repositorio como te he comentado es decir Te pudieras saltar perfectamente esta clase entonces si te quedaste es porque quieres ver la traducción obviamente voy a copiar y pegar para tener aquí toda la estructura y aprovechar y copiar los métodos.

Entonces, por aquí lo primero que voy a hacer es copiar aquí un poquito el contenido de la prueba creada con PHPUnit, para ya tenerla aquí lista esto es mucho copiar y pegar Recuerda que ya eso te lo he comentado aquí voy a quitar todo lo que no voy a necesitar en este caso estos dos creo que el de usuario también para ver si el de usuario tamb bien aunque no mentira…
Vamos con el siguiente voy a clonar darle un espacio sería este bueno test get by ID voy a cortar todo esto hasta acá la coloco te puedes ir dando cuenta de que todo es prácticamente lo mismo corto acá pudieras dejarla así como te comento, Pero prefiero tenerlo todo en una sola línea porque otra vez no estamos haciendo nada con la respuesta entonces lógicamente la podemos simplificar quito esto quito la referencia y este es el protocolo que tienes que seguir hasta terminar entonces, vamos a seguir hasta terminar esto sí voy a copiar el nombre Ah no lo coloco 404 estará para la parte de los errores sería por aquí por acá aquí ya tenemos uno con el heer hubiera que ver si aquí cuando lo hacemos con pest lo requiere en este caso sí lo requería si no mandaba no recuerdo si era en otra página pero de igual manera lo voy a definir ahí y pendiente con eliminar esto quedaría así una un Post que no existe y evaluamos aquí la respuesta aquí también duplico acá:

test('test all', function () {

    Category::factory(10);
    $categories = Category::get()->toArray();

    $this->get(
        '/api/category/all',
        [
            'Authorization' => 'Bearer ' . generateTokenAuth()
        ]
    )->assertOk()->assertJson($categories);
});

En esencia, debemos de quitar el assertHeader y se coloco como tercer parámetro aquí esto era una forma de hacerlo si no podías ir directamente al método de aserción con el database el de missing o si está definido que vimos más adelante:

$this->post('/api/category', $data, [
            'Accept' => 'application/json',
            'Authorization' => 'Bearer ' . $this->generateTokenAuth()
        ])

Para el remplazo del método se aserción assertStringContainsString que no existe en Pest, usamos assertMatchesRegularExpression que funciona a partir de hacer expresiones regular:

assertMatchesRegularExpression("/The title field is required./", $response->getContent());

… Seguimos un poco quitar este espacio enter aquí quito este aquí coloco put aquí un poco lo mismo, debería de ser lo pegamos la Data … el header y de tercer parámetro y evaluamos aquí la respuesta seguimos acá corto movemos el header … finalmente el último test delete solamente test delete pego acá vamos a quitar el respons a este no le pasamos:

it("test delete auth", function () {
    Category::factory(1)->create();
    $category = Category::first();

    $this->delete('/api/category/' . $category->id,[], [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(200)
        ->assertContent('"ok"');

    $category = Category::find($category->id);
    $this->assertEquals($category, null);
});

Y no tiene ningún problema con eso postes postes Ah ya es que repetí una de las pruebas para ver dos veces hay una que la dejé aquí también está mira aquí…

Resumen

Espero que te haya servido de igual manera te lo muestro si llegaste aquí ahora te voy a mostrar un poquito el código es tal cual te presentaba antes aquí le como te comenté al inicio como te he comentado en las anteriores revisiones le quité el response cuando no es necesario ya que la dejamos ahí como una variable muerta y por lo demás le movimos el header y el método de aserción de hacer machas regular expression para evaluar aquí la expresión regular que es un Stream ahí directamente que le estamos pasando por lo demás Todo queda exactamente igual así que ya con esto terminamos las pruebas para el post y faltaría la de usuarios que ya la hice tal cual puedes ver y te la muestro en el siguiente video.

Las pruebas con Pest no cambian mucho de las implementadas con PHPUnit, es una sintaxis un poco más simple y a continuación, se presenta las pruebas traducidas anteriormente con Pest:

tests/Feature/Api/CategoryTest.php

<?php
use App\Models\Category;

test('test all', function () {

    Category::factory(10);
    $categories = Category::get()->toArray();

    $this->get(
        '/api/category/all',
        [
            'Authorization' => 'Bearer ' . generateTokenAuth()
        ]
    )->assertOk()->assertJson($categories);
});

it("test get by id", function () {
    Category::factory(1)->create();
    $category = Category::first();

    $this->get('/api/category/' . $category->id, [
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(200)->assertJson([
                'id' => $category->id,
                'title' => $category->title,
                'slug' => $category->slug
            ]);
});
it("test get by slug", function () {
    Category::factory(1)->create();
    $category = Category::first();

    $this->get('/api/category/slug/' . $category->slug, [
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(200)->assertJson([
                'id' => $category->id,
                'title' => $category->title,
                'slug' => $category->slug
            ]);
});
it("test post", function () {
    $data = ['title' => 'Cate 1', 'slug' => 'cate-2-new'];
    $this->post('/api/category', $data, [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(200)->assertJson($data);
});
it("test post error form title", function () {
    $data = ['title' => '', 'slug' => 'cate-2-new'];
    $response = $this->post('/api/category', $data, [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(422);

    // $this->assertStringContainsString("The title field is required.", $response->getContent());
    $this->assertMatchesRegularExpression("/The title field is required./", $response->getContent());
    // $testArray = array("a"=>"value a", "b"=>"value b"); 
    // $value = "value b";  
    // // assert function to test whether 'value' is a value of array 
    // $this->assertContains($value, $testArray) ;

    // $this->assertContains("The title field is required.",['title'=>'["The title field is required."]']);
});
it("test post error form slug", function () {
    $data = ['title' => 'cate 3', 'slug' => ''];
    $response = $this->post('/api/category', $data, [
            'Accept' => 'application/json',
            'Authorization' => 'Bearer ' . $this->generateTokenAuth()
        ])->assertStatus(422);

    // $response->assertStringContainsString("The slug field is required.", $response->getContent());
    $this->assertMatchesRegularExpression("/The slug field is required./", $response->getContent());
});
it("test post error form slug unique", function () {
    Category::create(
        [
            'title' => 'category title',
            'slug' => 'cate-3'
        ]
    );

    $data = ['title' => 'cate 3', 'slug' => 'cate-3'];

    $response = $this->post('/api/category', $data, [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(422);

    $this->assertStringContainsString("The slug has already been taken.", $response->getContent());
});

it("test get by id 404", function () {
    $this->get('/api/category/1000', [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(404)->assertContent('"Not found"');

});
it("test get by slug 404", function () {
    $this->get('/api/category/slug/cate-not-exist', [
        'Accept' => 'application/json',
    ])->assertStatus(404)->assertContent('"Not found"');

});

it("test put", function () {
    Category::factory(1)->create();
    $categoryOld = Category::first();

    $dataEdit = ['title' => 'Cate new 1', 'slug' => 'cate-1-new'];

    $this->put('/api/category/' . $categoryOld->id, $dataEdit, [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(200)->assertJson($dataEdit);
});

it("test delete auth", function () {
    Category::factory(1)->create();
    $category = Category::first();

    $this->delete('/api/category/' . $category->id,[], [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer ' . $this->generateTokenAuth()
    ])->assertStatus(200)
        ->assertContent('"ok"');

    $category = Category::find($category->id);
    $this->assertEquals($category, null);
});

Al ser recursos protegidos por autenticación, definimos el método para generar el token dentro del a clase Pest:

tests/Pest.php

uses(TestCase::class, RefreshDatabase::class)->in('Feature');
function generateTokenAuth()
{
    User::factory()->create();
    return User::first()->createToken('myapptoken')->plainTextToken;
}

En el archivo anterior, también puedes ver que tienen el trait de RefreshDatabase que empleamos antes con PHPUnit.

- Andrés Cruz

In english

Este material forma parte de mi curso y libro completo; puedes adquirirlos desde el apartado de libros y/o cursos Curso y Libro Laravel 11 con Tailwind Vue 3, introducción a Jetstream Livewire e Inerta desde cero - 2025.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz En Udemy

Acepto recibir anuncios de interes sobre este Blog.

!Cursos desde!

10$

En Udemy

Quedan 3d 02:29!


Udemy

!Cursos desde!

4$

En Academia

Ver los cursos

!Libros desde!

1$

Ver los libros
¡Hazte afiliado en Gumroad!