0

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();
    }
1
  • First of all, do not use getenv, if Laravel changes what it is using for that, getenv will start failing... you have to use env or config... Also, NEVER call more than 1 endpoint in your tests... you have to setup everything that you will expect to have in that moment... because if one of those previous API fails and creates or returns something wrong, you are done for that test... Commented Dec 18, 2021 at 23:15

1 Answer 1

3

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);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.