You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

1 Días
4 Hrs
58 Min
22 Seg
Curso de Introducción a Laravel 6

Curso de Introducción a Laravel 6

Profesor Italo Morales F

Profesor Italo Morales F

Protección de una API con Login

36/37
Resources

How to set up protection on an API with guests?

Welcome! In this content, we explore the necessary configurations to protect an API against unauthenticated users, focusing on the use of token authentication. The key is to know what to do when you receive a guest user.

Why is it essential to have additional test methods?

  • Controlled development: Our controller has five methods, but at the testing level we add an additional one for validation.
  • Continuous improvement: It allows us to create new cases for specific situations, such as guest access.
  • Evaluate protection: We can verify how our system responds when unauthenticated users arrive.

How are the test methods configured?

  1. Define the expected behavior: We want to test the routes that receive guests.
  2. Configure the expected status: The status should be 401 - Unauthorized when trying to access without authentication.
public function testGuestAccess(){ $this->get('/happy')->assertStatus(401);}

What happens when you receive an incorrect status code?

  • Quick diagnosis: If you expect a 401 and receive a 200, the API is probably public.
  • Action needed: Make sure to secure the routes with middleware.

How to secure an API with middleware?

  • Configure the middleware: Use auth:api as middleware in routes/api.php to secure routes.
  • Token Authentication: Ideal for APIs, ensuring that only authenticated users can access.
Route::middleware('auth:api')->get('/happy', function (Request $request) { //});

How do you integrate all this into your tests?

  1. Create users: Use factories to simulate users.
  2. Test as an authenticated user: Use actingAs with the token.
$user = User::factory()->create();$this->actingAs($user, 'api')->get('/happy')->assertStatus(200);

What happens when running multiple tests?

  • Multiplicity: Duplicate the configuration to test all routes(POST, PUT, DELETE).
  • Full validation: Ensures that each route shows the expected behavior.

Example of PUT verification

$user = User::factory()->create();$this->actingAs($user, 'api')->put('/mil')->assertStatus(200);

What to expect after implementation?

  • Immediate feedback: When running the tests, you should see that the system responds properly under authentication, while blocking unauthorized access.
  • Guaranteed security: Make sure that each method is only accessible via token to protect your API.

Whenever you develop or adjust an API, practicing and evaluating the results is crucial. Share your experiences or doubts with us. On your way to technology mastery, every step counts - keep going and keep going!

Contributions 51

Questions 5

Sort by:

Want to see more contributions, questions and answers from the community?

Si estas trabajando con VSCode tienes la opcion de descargar un plugin que se llama phpUnit, con este pudes colocar el apuntador en cualquier metodo que desees probar y usando en Mac command+shift+p, en windows: ctrl+shift+p, podras llamar a un prompt ahi escribes la palabra test y tendras la opcion de correr todos o en el que te encuentras trabajando asi aceleras un poco mas tu workflow

En laravel 8 me respondía con un error 500

Tuve que agregar estas líneas en en los guards del archivo auth.php que está en la carpeta de config

'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],

Asumo que es por la versión del framework…Y todo correcto, espero sirva.

Pues todo perfecto! Al fin aprendí a crear un API, aunque no entiendo aún cómo es que el usuario se loguearía desde el front, pero por todo lo demás, perfecto! aquí dejo parte de mi código con las pruebas corriendo al 100

Tuve problemas con el middleware pero lo solucioné de esta manea.
api.php

 Route::apiResource('posts', PostController::class)->middleware('auth:sanctum');

PostControllerTest.php

$response = $this->actingAs($user, 'sanctum')->json

bueno solo tenemos que agregar estas lineas asi nos verifique estamos logueado
$user = factory(User::class)->create();

$this->actingAs($user, ‘api’)->json…

<?php

namespace Tests\Feature\Http\controllers\Api;

use App\Post;
use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class PostControllerTest extends TestCase
{

    use RefreshDatabase;

    public function test_store()
    {
        // $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => 'El post de prueba'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
            ->assertJson(['title' => 'El post de prueba'])
            ->assertStatus(201); // ok, creado un recurso

        $this->assertDatabaseHas('posts', ['title' => 'El post de prueba']);
    }

    public function test_validate_title()
    {
        $user = factory(User::class)->create();
        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => ''
        ]);

        $response->assertStatus(422) //estatus HTTP 422
            ->assertJsonValidationErrors('title');
    }

    public function test_show()
    {
        //  $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('GET', "/api/posts/$post->id"); //id = 1

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
            ->assertJson(['title' => $post->title])
            ->assertStatus(200); // ok
    }


    public function test_404_show()
    {
        $user = factory(User::class)->create();
        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts/1000'); //id = 1000

        $response->assertStatus(404); // no existe
    }

    public function test_update()
    {
        // $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $post = factory(Post::class)->create();
        $response = $this->actingAs($user, 'api')->json('PUT', "/api/posts/$post->id", [
            'title' => 'nuevo'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
            ->assertJson(['title' => 'nuevo'])
            ->assertStatus(200); // ok

        $this->assertDatabaseHas('posts', ['title' => 'nuevo']);
    }

    public function test_delete()
    {
        // $this->withoutExceptionHandling();
        $user = factory(User::class)->create();
        $post = factory(Post::class)->create();
        $response = $this->actingAs($user, 'api')->json('DELETE', "/api/posts/$post->id");

        $response->assertSee(null)
            ->assertStatus(204); // sin contenido

        $this->assertDatabaseMissing('posts', ['id' => $post->id]);
    }

    public function test_index()
    {
        factory(Post::class, 5)->create();
        $user = factory(User::class)->create();
        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts');

        $response->assertJsonStructure([
            'data' => [
                '*' => ['id', 'title', 'created_at', 'updated_at']
            ]
        ])->assertStatus(200);
    }

    public function test_guest()
    {
        $this->json('GET', '/api/posts')->assertStatus(401);
        $this->json('POST', '/api/posts')->assertStatus(401);
        $this->json('GET', '/api/posts/1000')->assertStatus(401);
        $this->json('PUT', '/api/posts/1000')->assertStatus(401);
        $this->json('DELETE', '/api/posts/1000')->assertStatus(401);
    }
}

Delete con TDD y Login


Para verificar si algo no existe en nuestra Databse con PHPUnit

$this->assertDatabaseMissing('posts', ['id' => $post->id]);

Para crear un autenticación en un api utilizamos el middleware

, PostController::class)->middleware('auth:api');

Y para arreglar nuestras anteriores testing vamos a crear un usuario y poner que estamos login con el token del Api

$user = User::factory()->create();

$response = $this->actingAs($user, 'api')->json('POST', ...

Todo funcionó como se esperaba. Me hubiera gustado probar la API desde otro programa consumiéndola.

Sería factible crear una sola vez la creación del usuario y reutilizar en todos los metodos?

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Post;
use App\Http\Requests\Post as PostRequests;

class PostController extends Controller
{
    private $post;

    /**
     * __construct
     *
     * @param  mixed $post
     * @return void
     */
    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return response()->json($this->post->paginate());
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(PostRequests $request)
    {
        $post = $this->post->create($request->all());
        return response()->json($post, 201);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function show(Post $post)
    {
        return response()->json($post);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(PostRequests $request, Post $post)
    {
        $post->update($request->all());

        return response()->json($post);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        $post->delete();

        return response()->json(null, 204);
    }
}

Mi primera API basica con el framework. 👌

Ejercicio

En laravel 9

Si estas con Laravel 8, es posible que te salga los siguientes errores:

InvalidArgumentException: Auth guard [api] is not defined.

Incluso, después de corregir el anterior error, te salga el siguiente:

RouteNotFoundException: Route [login] not defined.

Esto es porque si es un usuario que no esta autorizado, deberá redirigirse a la pagina Login. La forma más fácil de corregir el error es colocar en la ruta con el middleware lo siguiente:

Route::apiResource('posts', PostController::class)->middleware('auth.basic');

Mi test de todos los métodos.

public function test_guest()
{
    $this->json('GET', '/api/posts')->assertStatus(401);
    $this->json('POST', '/api/posts')->assertStatus(401);
    $this->json('GET', '/api/posts/1000')->assertStatus(401);
    $this->json('PUT', '/api/posts/1000')->assertStatus(401);
    $this->json('DELETE', '/api/posts/1000')->assertStatus(401);
}

VICTORY!

class PostTest extends TestCase
{
    use RefreshDatabase;

    public function test_store()
    {
        //$this->withoutExceptionHandling(); //PARA TESTING DETALLADO
        $user = factory(User::class)->create();

        $response = $this->actingAs($user,'api')->json('POST','/api/posts',[
            'title' => 'El Post de Prueba'
        ]);

        $response->assertJsonStructure(['id','title','created_at','updated_at'])
            ->assertJson(['title' => 'El Post de Prueba'])
            ->assertStatus(201); //OK Y CREADO UN RECURSO : CODIGO 201
        

        $this->assertDatabaseHas('posts',['title' => 'El Post de Prueba']);
    }

    public function test_validate_title()
        {
            $user = factory(User::class)->create();

            $response = $this->actingAs($user,'api')->json('POST','/api/posts',[
                'title' => ''
            ]);

            $response->assertStatus(422) //estatus 422: Imposible de completar
                ->assertJsonValidationErrors('title');
        }

    public function test_show()
    {
        $post = factory(Post::class)->create();
        $user = factory(User::class)->create();

        $response = $this->actingAs($user,'api')->json('GET',"/api/posts/$post->id"); //id=1

        $response->assertJsonStructure(['id','title','created_at','updated_at'])
        ->assertJson(['title' => $post->title])
        ->assertStatus(200); //OK 
    }

    public function test_404_show()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user,'api')->json('GET','/api/posts/1000'); //id=1

        $response->assertStatus(404); //Recurso no encontrado
    }

    public function test_update()
    {
        $this->withoutExceptionHandling(); //PARA TESTING DETALLADO
        $post = factory(Post::class)->create();
        $user = factory(User::class)->create();

        $response = $this->actingAs($user,'api')->json('PUT',"/api/posts/$post->id",[
            'title' => 'nuevo'
        ]);

        $response->assertJsonStructure(['id','title','created_at','updated_at'])
            ->assertJson(['title' => 'nuevo'])
            ->assertStatus(200); //OK Y CREADO UN RECURSO : CODIGO 201
        

        $this->assertDatabaseHas('posts',['title' => 'nuevo']);
    }

    public function test_delete()
    {
        //$this->withoutExceptionHandling(); //PARA TESTING DETALLADO
        $post = factory(Post::class)->create();
        $user = factory(User::class)->create();

        $response = $this->actingAs($user,'api')->json('DELETE',"/api/posts/$post->id");

        $response->assertSee(null)
            ->assertStatus(204); //SIN CONTENIDO : CODIGO 204
        

        $this->assertDatabaseMissing('posts',['id' => $post->id]);
    }

    public function test_index()
    {
        factory(Post::class,5)->create();
        $user = factory(User::class)->create();

        $response = $this->actingAs($user,'api')->json('GET','/api/posts');

        $response->assertJsonStructure([
            'data'=>[
                '*' => ['id','title','created_at','updated_at']
            ]])->assertStatus(200);
    }

    public function test_guest()
    {
        $this->json('GET','/api/posts')->assertStatus(401);
        $this->json('POST','/api/posts')->assertStatus(401);
        $this->json('GET','/api/posts/1000')->assertStatus(401);
        $this->json('PUT','/api/posts/1000')->assertStatus(401);
        $this->json('DELETE','/api/posts/1000')->assertStatus(401);

    }


}

Resultados prueba =>

php artisan test                  
Warning: TTY mode is not supported on Windows platform.

   PASS  Tests\Feature\Http\Controllers\Api\PostControllerTest  ✓ store
  ✓ validate title
  ✓ show404 showupdatedeleteindex
  ✓ guest

  Tests:  8 passed
  Time:   0.90s

Cuando ejecutaba las pruebas me apareció error 500 InvalidArgumentException: Auth guard [api] is not defined, lo resolvi con este post =>

https://www.py4u.net/discuss/59367

LARAVEL 8

    public function test_store()
    {
        $user = User::factory()->create();
        // Llamada al manejador de errores para mostrar de manera más concisa la falla.
        //$this->witOutExceptionHandling();

        /* 
            Simulación de una aplicación esta llegando mediante la ruta
            /api/posts y esta intentando guardar los datos mediante el
            método post.
        */        
        $response = $this->actingAs($user, 'api')->postJson('/api/posts',[
            'title' => 'El Post de prueba'
        ]);


        /* 
            Comprobar que se esta guardando los datos
            ->assertJsonStructure() : confirmación de estructura
            ->assertJson() : Confirmación de dato existente en Json
            ->assertStatus(201) : Confirmación de status
        */        
        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                 ->assertJson(['title' => 'El Post de prueba'])
                 ->assertStatus(201);

        $this->assertDatabaseHas('posts', ['title' => 'El Post de prueba']);         
    }   

    public function test_validar_title()
    {
        $user = User::factory()->create();
        $response = $this->actingAs($user, 'api')->postJson('/api/posts',[
            'title' => ''
        ]);        

        $response->assertStatus(422)
                ->assertJsonValidationErrors('title');
    }

    public function test_show()
    {
        $user = User::factory()->create();
        $post = Post::factory()->create();

        $response = $this->actingAs($user, 'api')->json("GET", "/api/posts/$post->id");

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                 ->assertJson(['title'=> $post->title])
                 ->assertStatus(200); // OK
    }

    public function test_404_show()
    {
        $user = User::factory()->create();
        $response = $this->actingAs($user, 'api')->json("GET", '/api/posts/1000');

        $response->assertStatus(404);
    }


    public function test_update()
    {
        $post = Post::factory()->create();
        $user = User::factory()->create();

        $response = $this->actingAs($user, 'api')->json('PUT',"/api/posts/$post->id",[
            'title' => 'nuevo'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
        ->assertJson(['title'=> 'nuevo'])
        ->assertStatus(200); // OK

        $this->assertDatabaseHas('posts',['title' => 'nuevo']);
    }

    public function test_delete()
    {
        $post = Post::factory()->create();
        $user = User::factory()->create();
        
        $response = $this->actingAs($user, 'api')->json('DELETE', "/api/posts/$post->id");
    
        $response->assertSee(null)
                 ->assertStatus(204); // Sin contenido    

        $this->assertDatabaseMissing('posts',['id' => $post->id]);                 

    }

    public function test_index()
    {
        // $this->withOutExceptionHandling();
        $user = User::factory()->create();
        Post::factory()->count(5)->create();

        $response = $this->actingAs($user, 'api')->json('GET',"api/posts");
    
        $response->assertJsonStructure([
            'data'  => [
                '*' => ['id', 'title', 'created_at', 'updated_at']
            ]
        ])->assertStatus(200);    
    }

    public function test_guest()
    {
        $this->json('GET',     'api/posts')->assertStatus(401);
        $this->json('POST',    'api/posts')->assertStatus(401);
        $this->json('GET',     'api/posts/1000')->assertStatus(401);
        $this->json('PUT',     'api/posts/1000')->assertStatus(401);
        $this->json('DELETE',  'api/posts/1000')->assertStatus(401);
    }

PostControllerTes:

namespace Tests\Feature\Http\Controllers\Api;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\Post;
use App\User;

class PostControllerTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Feature for store post test.
     *
     */
    public function test_store()
    {
        // $this->withoutExceptionHandling();
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => 'El post de prueba'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                ->assertJson(['title' => 'El post de prueba'])
                ->assertStatus(201); //OK, resource created

        $this->assertDatabaseHas('posts', ['title' => 'El post de prueba']);
    }

    /**
     * Feature for title validation test
     *
     */
    public function test_validate_title()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => ''
        ]);

        //Status HTTP 422 resource not complete
        $response->assertStatus(422)
                ->assertJsonValidationErrors('title');
    }

    /**
     * Feature for show a post test
     *
     */
    public function test_show()
    {
        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('GET', "/api/posts/$post->id");

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                ->assertJson(['title' => $post->title])
                ->assertStatus(200); //OK
    }

    /**
     * Feature for not available show a post test
     *
     */
    public function test_404_show()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts/1000');

        $response->assertStatus(404); //Not available post
    }

    /**
     * Feature for update a post test
     *
     */
    public function test_update()
    {
        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('PUT', "/api/posts/$post->id", [
            'title' => 'Nuevo'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                ->assertJson(['title' => 'Nuevo'])
                ->assertStatus(200); //OK

        $this->assertDatabaseHas('posts', ['title' => 'Nuevo']);
    }

    /**
     * Feature for delete a post test
     *
     */
    public function test_delete()
    {
        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('DELETE', "/api/posts/$post->id");

        $response->assertSee(null)
                ->assertStatus(204); //OK

        $this->assertDatabaseMissing('posts', ['id' => $post->id]);
    }

    /**
     * Feature for list all resources test
     *
     */
    public function test_index()
    {
        $user = factory(User::class)->create();

        factory(Post::class, 5)->create();

        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts');

        $response->assertJsonStructure([
            'data' => [
                '*' => ['id', 'title', 'created_at', 'updated_at']
            ]
        ])->assertStatus(200); //OK
    }

    /**
     * Feature for login test
     *
     */
    public function test_guest()
    {
        $this->json('GET', 'api/posts')->assertStatus(401);
        $this->json('POST', 'api/posts')->assertStatus(401);
        $this->json('GET', 'api/posts/1000')->assertStatus(401);
        $this->json('PUT', 'api/posts/1000')->assertStatus(401);
        $this->json('DELETE', 'api/posts/1000')->assertStatus(401);
    }
}

PostController:

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Http\Request;
use App\Http\Requests\Post as PostRequests;

class PostController extends Controller
{
    protected $post;

    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return response()->json(
            $this->post->paginate(), 200
        );
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(PostRequests $request)
    {
        $post = $this->post->create($request->all());

        return response()->json($post, 201);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function show(Post $post)
    {
        return response()->json($post, 200);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(PostRequests $request, Post $post)
    {
        $post->update($request->all());

        return response()->json($post, 200);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        $post->delete();

        return response()->json(null, 204);
    }
}

PostControllerTest:

<?php

namespace Tests\Feature\Http\Controllers\Api;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\Post;
use App\User;

class PostControllerTest extends TestCase
{
    use RefreshDatabase;

    /**
     * Feature for store post test.
     *
     */
    public function test_store()
    {
        // $this->withoutExceptionHandling();
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => 'El post de prueba'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                ->assertJson(['title' => 'El post de prueba'])
                ->assertStatus(201); //OK, resource created

        $this->assertDatabaseHas('posts', ['title' => 'El post de prueba']);
    }

    /**
     * Feature for title validation test
     *
     */
    public function test_validate_title()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => ''
        ]);

        //Status HTTP 422 resource not complete
        $response->assertStatus(422)
                ->assertJsonValidationErrors('title');
    }

    /**
     * Feature for show a post test
     *
     */
    public function test_show()
    {
        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('GET', "/api/posts/$post->id");

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                ->assertJson(['title' => $post->title])
                ->assertStatus(200); //OK
    }

    /**
     * Feature for not available show a post test
     *
     */
    public function test_404_show()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts/1000');

        $response->assertStatus(404); //Not available post
    }

    /**
     * Feature for update a post test
     *
     */
    public function test_update()
    {
        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('PUT', "/api/posts/$post->id", [
            'title' => 'Nuevo'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
                ->assertJson(['title' => 'Nuevo'])
                ->assertStatus(200); //OK

        $this->assertDatabaseHas('posts', ['title' => 'Nuevo']);
    }

    /**
     * Feature for delete a post test
     *
     */
    public function test_delete()
    {
        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('DELETE', "/api/posts/$post->id");

        $response->assertSee(null)
                ->assertStatus(204); //OK

        $this->assertDatabaseMissing('posts', ['id' => $post->id]);
    }

    /**
     * Feature for list all resources test
     *
     */
    public function test_index()
    {
        $user = factory(User::class)->create();

        factory(Post::class, 5)->create();

        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts');

        $response->assertJsonStructure([
            'data' => [
                '*' => ['id', 'title', 'created_at', 'updated_at']
            ]
        ])->assertStatus(200); //OK
    }

    /**
     * Feature for login test
     *
     */
    public function test_guest()
    {
        $this->json('GET', 'api/posts')->assertStatus(401);
        $this->json('POST', 'api/posts')->assertStatus(401);
        $this->json('GET', 'api/posts/1000')->assertStatus(401);
        $this->json('PUT', 'api/posts/1000')->assertStatus(401);
        $this->json('DELETE', 'api/posts/1000')->assertStatus(401);
    }
}

Se debe realizar todas las fallas que puede existir en cada uno de los metodos

Buenas compañeros, queria traer una duda terminando esta ultima leccion hice la ultima prueba pero me sale este error
![](

intente ensayar probando cada metodo y estan bien pero, al probar el test_guest() es alli donde me salio ese error

Listo, practica terminada

Excelente genial la protección por API

Muy buen curso!

Excelente!!! Lo esperado!!!

Api con protección…

Excelente 😃 ! Todo super. Gracias

Wow! esto es muy interesante!

Les comparto mi resultado final 😀

![](

Excelente guia

OK (8 tests, 55 assertions)

Todo el codigo del miniproject

<?php

namespace Tests\Feature\Http\Controllers\Api;

use App\Post;
use App\User;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PostTest extends TestCase
{
    use RefreshDatabase;

    /**
     *
     * @return void
     * @test
     */
    public function canSaveWithStore()
    {
        $this->withoutExceptionHandling();
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => 'El post de prueba'
        ]);

        $response->assertJsonStructure(['id','title', 'created_at', 'updated_at'])
        ->assertJson(['title' => 'El post de prueba'])
        ->assertStatus(201);

        $this->assertDatabaseHas('posts', ['title' => 'El post de prueba']);
    }

    /**
     *
     * @return void
     * @test
     */
    public function validatePostWithTitle()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('POST', '/api/posts', [
            'title' => ''
        ]);

        $response->assertStatus(422)
        ->assertJsonValidationErrors('title');
    }

    /**
     *
     * @return void
     * @test
     */
    public function postCanShow()
    {
        $user = factory(User::class)->create();
        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('GET', "/api/posts/$post->id", [
            'title' => ''
        ]);

        $response->assertJsonStructure(['id','title', 'created_at', 'updated_at'])
            ->assertJson(['title' => $post->title])
            ->assertStatus(200);
    }

    /**
     *
     * @return void
     * @test
     */
    public function cantShowNonexistentPost()
    {
        $user = factory(User::class)->create();

        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts/1000', [
            'title' => ''
        ]);

        $response->assertStatus(404);
    }

    /**
     *
     * @return void
     * @test
     */
    public function canUpdatePosts()
    {
        //$this->withoutExceptionHandling();

        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('PUT', "/api/posts/$post->id", [
            'title' => 'Nuevo'
        ]);

        $response->assertJsonStructure(['id','title', 'created_at', 'updated_at'])
            ->assertJson(['title' => 'Nuevo'])
            ->assertStatus(200);

        $this->assertDatabaseHas('posts', ['title' => 'Nuevo']);
    }

    /**
     *
     * @return void
     * @test
     */
    public function canDeletePosts()
    {
        //$this->withoutExceptionHandling();

        $user = factory(User::class)->create();

        $post = factory(Post::class)->create();

        $response = $this->actingAs($user, 'api')->json('DELETE', "/api/posts/$post->id");

        $response->assertSee(null)
            ->assertStatus(204);

        $this->assertDatabaseMissing('posts', ['id' => $post->id]);
    }

    /**
     *
     * @return void
     * @test
     */
    public function indexPosts()
    {
        $user = factory(User::class)->create();

        factory(Post::class,5)->create();

        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts');

        $response->assertJsonStructure([
            'data' => [
                '*' => ['id', 'title', 'created_at', 'updated_at']
            ]
        ])->assertStatus(200);
    }

    /**
     *
     * @return void
     * @test
     */
    public function aGuestArrive()
    {
        $this->json('GET', '/api/posts')->assertStatus(401);
        $this->json('POST', '/api/posts')->assertStatus(401);
        $this->json('GET', '/api/posts/1000')->assertStatus(401);
        $this->json('PUT', '/api/posts/1000')->assertStatus(401);
        $this->json('DELETE', '/api/posts/1000')->assertStatus(401);
    }
}

Resultado conseguido y con montón de conocimiento nuevo que aplicar a mis futuros proyectos 😄. Gracias Profesor Italo Morales.

En que curso de platzi se ve como usar una Api de este tipo?
saludos

$ php artisan test
Warning: TTY mode is not supported on Windows platform.

   PASS  Tests\Feature\Http\Controllers\Api\PostControllerTest
  ✓ store
  ✓ validate titleshow404 show
  ✓ update
  ✓ delete
  ✓ index
  ✓ guest

  Tests:  8 passed
  Time:   1.88s

en Laravel 8.x al usar el middleware en las rutas arroja status 405 y no 401, eso es correcto?

Genial ! Este es mi resultado , aplicando los Test de este Curso

compartiendo todo el código:


<?php

namespace Tests\Feature\Htt\Controllers\Api;

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

use App\Models\Post;
use App\Models\User;

class PostControllerTest extends TestCase
{
    use RefreshDatabase;
    /**
     * A basic feature test example.
     *
     * @return void
     */
    
    public function test_store()
    {
        //$this->withoutExceptionHandling();

        $user = User::factory()->create();

        $response = $this->actingAs($user, 'api')->json('POST','/api/posts',[
            'title' => 'El post de prueba'
            ]);

        $response->assertJsonStructure(['id','title', 'created_at','updated_at'])
            ->assertJson(['title' => 'El post de prueba'])
            ->assertStatus(201); //OK creado un recurso

        $this->assertDatabaseHas('posts',['title' => 'El post de prueba']);
    }


    public function test_validate_title()
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user, 'api')->json('POST','/api/posts',[
            'title' => ''
            ]);

        $response->assertStatus(422) //estatus HTTP 422 fue imposible guardarla
                 ->assertJsonValidationErrors('title');
    }

    public function test_show()
    {

        $this->withoutExceptionHandling();
        $user = User::factory()->create();
        $post = Post::factory()->create();

        $response = $this->actingAs($user, 'api')->json('GET', "/api/posts/$post->id"); // id =1

        $response->assertJsonStructure(['id','title', 'created_at','updated_at'])
            ->assertJson(['title' => $post->title])
            ->assertStatus(200); //OK creado un recurso
    }


    public function test_404_show()
    {

        //$this->withoutExceptionHandling();

        //$post = Post::factory()->create();
        $user = User::factory()->create();
        $response = $this->actingAs($user, 'api')->json('GET', '/api/posts/1000'); // id =1

        $response->assertStatus(404); //OK creado un recurso
    }

    public function test_update()
    {
        // $this->withoutExceptionHandling();
        $user = User::factory()->create();
        $post = Post::factory()->create();
        $response = $this->actingAs($user, 'api')->json('PUT', "/api/posts/$post->id", [
            'title' => 'nuevo'
        ]);

        $response->assertJsonStructure(['id', 'title', 'created_at', 'updated_at'])
            ->assertJson(['title' => 'nuevo'])
            ->assertStatus(200); // ok

        $this->assertDatabaseHas('posts', ['title' => 'nuevo']);
    }

    public function test_delete()
    {
        // $this->withoutExceptionHandling();
        $user = User::factory()->create();
        $post = Post::factory()->create();
        $response = $this->actingAs($user, 'api')->json('DELETE', "/api/posts/$post->id");

        $response->assertSee(NULL)->assertStatus(204); // ok

        $this->assertDatabaseMissing('posts', ['id' => $post->id]);
    }

    public function test_index()
    {
        // $this->withoutExceptionHandling();
        $user = User::factory()->create();
        $post = Post::factory()->count(5)->create();
        $response = $this->actingAs($user, 'api')->json('GET', "/api/posts");

        $response->assertJsonStructure([
            'data' => [
                '*' => ['id','title','created_at','updated_at']
            ]
        ])->assertStatus(200);
    }


    public function test_guest()
    {
        // $this->withoutExceptionHandling();
        $this->json('GET', "/api/posts")->assertStatus(401);
        $this->json('POST', "/api/posts")->assertStatus(401);
        $this->json('GET', "/api/posts/1000")->assertStatus(401);
        $this->json('PUT', "/api/posts/1000")->assertStatus(401);
        $this->json('DELETE', "/api/posts/1000")->assertStatus(401);
    }



}