Home > OS >  PHPUnit API Testing returns unauthenticated in some post requests
PHPUnit API Testing returns unauthenticated in some post requests

Time:12-18

I am trying to test my Laravel API, but in some cases where I submit a post request I receive a 401 error with the message "Unauthenticated". All the GET requests that are protected are properly accessible and certain POST requests like submitting a status are also doing fine. Why do I get the 401 error in some cases, but not in others?

Here are the files
API Routes

Route::group(['middleware' => ['auth:sanctum']], function() {
    Route::get('logout', [MantelAuthController::class, 'logout']);
    
    Route::post('status', [MantelController::class, 'status']);
    Route::post('deleteAccount', [MantelController::class, 'deleteAccount']);
});

Logout test

public function test_logoutAPI()
    {
        $testEmail = getenv('TEST_EMAIL_API');
        $testPassword = getenv('TEST_PASSWORD_API');

        $response = $this->post('/api/login', [
            'email' => $testEmail,
            'password' => $testPassword
        ]);

        $auth =  $response->assertStatus(201)->decodeResponseJson()['token'];
        
        $response = $this->get('/api/logout', 
        [
            'Authorization' => "Bearer ".$auth
        ]);
        $response->assertStatus(200);
    }

Send status test

public function test_post_status()
    {
        $testEmail = getenv('TEST_EMAIL_API2');
        $testPassword = getenv('TEST_PASSWORD_API');

        // log in
        $response = $this->post('/api/login', [
            'email' => $testEmail,
            'password' => $testPassword
        ]);
        $auth = $response->assertStatus(201)->decodeResponseJson()['token'];

        // get correct datetime
        $response = $this->get('/api/getData', 
        [
            'Authorization' => "Bearer ".$auth
        ]);
        $date= $response->assertStatus(200)->decodeResponseJson()['date'];
        
        // submit post request
        $response = $this->post('/api/status', 
        [
            'Authorization' => "Bearer ".$auth,
            'status' => "secure",
            'date' => $date
        ]);
        $response->assertCreated();
    }

Delete Account test

public function test_delete_account()
    {
        $DeletedEmail = "[email protected]";
        $DeletedPassword = "temporary";

        $response = $this->post('/api/login', [
            'email' => $DeletedEmail,
            'password' => $DeletedPassword
        ]);
        $auth = $response->assertStatus(201)->decodeResponseJson()['token'];
        
        $response = $this->withHeaders(['Accept' => 'application/json'])
        ->post('/api/deleteAccount', [
            'Authorization' => "Bearer ".$auth,
            'password' => $DeletedPassword
        ]);
        $response->assertSuccessful();
    }

CodePudding user response:

Part of your issue is you are mixing your header data and post data. You should try using withHeaders

https://laravel.com/docs/8.x/http-tests#customizing-request-headers

$response = $this->withHeaders([
            'X-Header' => 'Value',
        ])->post('/user', ['name' => 'Sally']);

You also don't have to actually login via your API route request for every test as this is pretty inefficient. You should have a test for your login API route, but you should be accessing the user model and using actingAs to set the authentication for your other requests.

https://laravel.com/docs/5.2/testing#sessions-and-authentication

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $user = factory(App\User::class)->create();

        $this->actingAs($user)
             ->withSession(['foo' => 'bar'])
             ->visit('/')
             ->see('Hello, '.$user->name);
    }
}
  • Related