Summer Sale! All accounts are 50% off this week.

AlunR's avatar
Level 3

PHPUnit - This action is unauthorized. Post request

I'm taking my first steps into testing and am following the Birdboard TDD tutorial with a few changes due to L9 instead of L5.7

I have a Test I made using artisan make:test ResourcesTest and in it I have:

/** @test */
public function a_user_can_create_a_resource()
{

    $this->withoutExceptionHandling();

    $attributes = [
                'name' => $this->faker->sentence,
            ];

    $response = $this->post('/resources', $attributes);

    $response->assertStatus(200);

    $this->assertDatabaseHas('resources', $attributes);

}

I have built the route, db migration, model and controller and can see it all working but when I post using Postman I get a Page Expired error as I'm not providing CSRF.

When I try and run my test I get the following error:

Illuminate\Auth\Access\AuthorizationException 
This action is unauthorized.

I've modified PHPUNIT.xml. accordingly but I'm still stumped!

<env name="APP_ENV" value="testing"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
0 likes
6 replies
adityakunhare's avatar

This is because you must have the respective route wrapped in an auth middleware...

For that you need to use

$this->actingAs(User::factory()))

Before hitting the ' resource' route in the test

AlunR's avatar
Level 3

I haven't got as far as adding an authentication method. This is the route:

Route::post('/resources', [ResourceController::class, 'store']);
AlunR's avatar
Level 3

I can visit the /resources url with a GET request just fine.

Route::get('/resources', [ResourceController::class, 'index']);
AlunR's avatar
Level 3
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ResourceController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});


Route::get('/resources', [ResourceController::class, 'index']);
Route::post('/resources', [ResourceController::class, 'store']);

Route::middleware([
    'auth:sanctum',
    config('jetstream.auth_session'),
    'verified'
])->group(function () {
    Route::get('/dashboard', function () {
        return view('dashboard');
    })->name('dashboard');
});
AlunR's avatar
Level 3

Solved it! I made the controller using make:model -a which created a StoreResourceRequest class.

This contains a function:

/**
 * Determine if the user is authorized to make this request.
 *
 * @return bool
 */
public function authorize()
{
    return true;
}

So changing this to true made all the difference!

Thank you for helping!

1 like

Please or to participate in this conversation.