A good tip is to use
$this->withoutExceptionHandling();
When in doubt why it isn't working. Just put it in above the user creation.
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
<?php
namespace Tests\Feature;
use App\Article;
use Tests\TestCase;
use App\Models\User;
use Database\Seeders\UserSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ProviderTest extends TestCase
{
//use DatabaseMigrations;
use RefreshDatabase;
public function test_provider_user_can_access_provider_section()
{
// Create a provider User
$user = User::create([
'name' => 'someuser',
'email' => '[email protected]',
'password' => bcrypt('abcdabcd'),
'is_provider' => 1,
]);
// Go to provider section - /provider/
$response = $this->actingAs($user)->get('/provider');
// Assert status - 200
$response->assertStatus(200);
}
}
The above works well when i check it manually. I doubt whether this has something to do with the provider keyword
A good tip is to use
$this->withoutExceptionHandling();
When in doubt why it isn't working. Just put it in above the user creation.
@tray2 Thank you for that Tip
@zaster How are we supposed to help? You haven’t told us what you do get if you say this isn’t working. You‘ve not really given us much to go on…
@martinbean Sorry about that
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
class ProviderTest extends TestCase
{
//use DatabaseMigrations;
use RefreshDatabase;
public function test_provider_user_can_access_provider_section()
{
$this->withoutExceptionHandling();
// Create a provider User
$user = User::create([
'name' => 'bob',
'email' => '[email protected]',
'password' => bcrypt('abcdaabcd'),
'is_provider' => 1,
]);
// Go to provider section - /provider/
$response = $this->actingAs($user)->get('/provider');
// Assert status - 200
$response->assertStatus(200);
}
public function test_admin_user_cannot_access_provider_section()
{
// Create an admin User
$user = User::create([
'name' => 'bob',
'email' => '[email protected]',
'password' => bcrypt('abcdaabcd'),
'is_admin' => 1,
]);
// Go to provider section - /provider/
$response = $this->actingAs($user)->get('/provider');
// Assert status NOT - 200
$response->assertStatus(403);
}
public function test_customer_user_cannot_access_provider_section()
{
// Create a customer User
$user = User::create([
'name' => 'bob',
'email' => '[email protected]',
'password' => bcrypt('abcdaabcd'),
'is_customer' => 1,
]);
// Go to provider section - /provider/
$response = $this->actingAs($user)->get('/provider');
// Assert status NOT - 200
$response->assertStatus(403);
}
public function test_employee_user_cannot_access_provider_section()
{
// Create an employee User
$user = User::create([
'name' => 'bob',
'email' => '[email protected]',
'password' => bcrypt('abcdaabcd'),
'is_employee' => 1,
]);
// Go to provider section - /provider/
$response = $this->actingAs($user)->get('/provider');
// Assert status NOT - 200
$response->assertStatus(403);
}
}
When i run
php artisan test
FAIL Tests\Feature\ProviderTest
⨯ provider user can access provider section
✓ admin user cannot access provider section
✓ customer user cannot access provider section
✓ employee user cannot access provider section
• Tests\Feature\ProviderTest > provider user can access provider section
Expected status code 200 but received 403.
Failed asserting that 200 is identical to 403.
at tests/Feature/ProviderSectionTest.php:29
25▕ // Go to provider section - /provider/
26▕ $response = $this->actingAs($user)->get('/provider');
27▕
28▕ // Assert status - 200
➜ 29▕ $response->assertStatus(200);
30▕
31▕ }
32▕
33▕ public function test_admin_user_cannot_access_provider_section()
It works with
$response->assertStatus(403);
But it shouldn't
Another clue - I renamed everything from vendor to provider (Initially i thought the provider should be named as vendor , then i changed everything)
I have run composer dump-autoload
and this is what i get
Class Tests\Feature\ProviderTest located in ./tests/Feature/ProviderSectionTest.php does not comply with psr-4 autoloading standard. Skipping.
403 means forbidden. So most likely the user you are creating isn't a "provider" user.
But that is not the case. The User is a provider. I have tried other tests on other types of users and those worked
PASS Tests\Feature\AdmniSectionTest
✓ admin user can access admin section
✓ customer user cannot access admin section
✓ employee user cannot access admin section
✓ provider user cannot access admin section
PASS Tests\Feature\CustomerTest
✓ customer user can access customer section
✓ admin user cannot access customer section
✓ employee user cannot access customer section
✓ provider user cannot access customer section
PASS Tests\Feature\EmployeeTest
✓ employee user can access employee section
✓ admin user cannot access employee section
✓ customer user cannot access employee section
✓ provider user cannot access employee section
Only this doesn't work
FAIL Tests\Feature\ProviderTest
⨯ provider user can access provider section
✓ admin user cannot access provider section
✓ customer user cannot access provider section
✓ employee user cannot access provider section
As i mentioned earlier provider was named as vendor before and i doubt something was not changed or kind of not refreshed.
But everything works when i test manually
The php file is named ProviderSectionTest.php
but the classname inside the file is ProviderTest
that is why it is skipping that file the filename and the class name need to be the same.
that could be the whole problem but for sure a problem.
fix that and run composer dump-autoload and then run your tests again.
Edit
Class Tests\Feature\ProviderTest located in ./tests/Feature/ProviderSectionTest.php does not comply with psr-4 autoloading standard. Skipping.
that could be the whole problem but for sure a problem.
YES. it sure was a problem corrected all the naming issues(AdminSectionTest, CustomerSectionTest, EmployeeSectionTest and ProviderSectionTest)
Class Tests\Feature\ProviderTest located in ./tests/Feature/ProviderSectionTest.php does not comply with psr-4 autoloading standard. Skipping.
is Sorted now.
Unfortunately the main error still exists
• Tests\Feature\ProviderSectionTest > provider user can access provider section
Expected status code 200 but received 403.
Failed asserting that 200 is identical to 403.
at tests/Feature/ProviderSectionTest.php:29
25▕ // Go to provider section - /provider/
26▕ $response = $this->actingAs($user)->get('/provider');
27▕
28▕ // Assert status - 200
➜ 29▕ $response->assertStatus(200);
30▕
31▕ }
32▕
33▕ public function test_admin_user_cannot_access_provider_section()
@zaster What middleware or protections do you have on that route? Because that user is not authorized. Post the route and the controller action for /provider
//Authenticated routes
Route::group(['middleware' => 'auth'], function() {
Route::get('/home', [HomeController::class, 'index'])->name('home');
Route::get('/dashboard', [DashboardController::class, 'index']);
//Admin Routes
Route::group(['middleware' => 'is_admin'], function() {
Route::prefix('admin')->name('admin.')->group(function (){
Route::get('/', [AdminDashboardController::class, 'index'])->name('dashboard.index');
Route::get('/user/', [AdminUserController::class, 'index'])->name('user.index');
Route::get('/user/{user}/edit', [AdminUserController::class, 'edit'])->name('user.edit');
Route::put('/user/{user}', [AdminUserController::class, 'update'])->name('user.update');
Route::delete('/user/{user}', [AdminUserController::class, 'destory'])->name('user.destroy');
});
});
//Customer Routes
Route::group(['middleware' => 'is_customer'], function() {
Route::prefix('customer')->name('customer.')->group(function (){
Route::get('/', [CustomerDashboardController::class, 'index'])->name('dashboard.index');
});
});
//Employee Section
Route::group(['middleware' => 'is_employee'], function() {
Route::prefix('employee')->name('employee.')->group(function (){
Route::get('/', [EmployeeDashboardController::class, 'index'])->name('dashboard.index');
});
});
//Provider Section
Route::group(['middleware' => 'is_provider'], function() {
Route::prefix('provider')->name('provider.')->group(function (){
Route::get('/', [ProviderDashboardController::class, 'index'])->name('dashboard.index');
});
});
});
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'is_admin' => IsAdminMiddleware::class,
'is_customer' => IsCustomerMiddleware::class,
'is_employee' => IsEmployeeMiddleware::class,
'is_provider' => IsProviderMiddleware::class,
];
what is in the is_provider middleware?
@zaster I would compare my middleware for customer, admin, employee with the provider middleware something is different.
<?php
namespace App\Http\Middleware;
use Closure;
class IsProviderMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!auth()->user()->is_provider) {
abort(403);
}
return $next($request);
}
}
Just a stupid test. Change the middleware temporarily and do an abort(401) instead. If the test then fails with a 401 you now that the user isn't a provider.
are the other middleware the same?
yes
<?php
namespace App\Http\Middleware;
use Closure;
class IsAdminMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!auth()->user()->is_admin) {
abort(403);
}
return $next($request);
}
}
<?php
namespace App\Http\Middleware;
use Closure;
class IsCustomerMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!auth()->user()->is_customer) {
abort(403);
}
return $next($request);
}
}
<?php
namespace App\Http\Middleware;
use Closure;
class IsEmployeeMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!auth()->user()->is_employee) {
abort(403);
}
return $next($request);
}
}
is it cast to boolean in migration?
@lemmon yes
$table->boolean('is_admin')->default(0);
$table->boolean('is_customer')->default(0);
$table->boolean('is_employee')->default(0);
$table->boolean('is_provider')->default(0);
@zaster are you testing in db or memory?
dump the user right before the get call in the test
dd($user)
// Go to provider section - /provider/
$response = $this->actingAs($user)->get('/provider');
what do you get?
Do you have is_provider in the fillable array on the User model?
Oh No!
You cracked it. :)
class User extends Authenticatable
{
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
use Historyable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
'is_admin',
'is_customer',
'is_employee',
'is_provider', //previously it was mentioned as **is_vendor**
];
A learning experience for us all, Kool :)
you should have die dumped the user and you would have seen it was null.
Yes. :)
@tray2 and @lemmon Thank you for your support
@martinbean Thank you for guiding me in the first place
As @tray2 said, the user was not a provider
@lemmon Yes @tray2 had it from the beginning
I couldn't figure it out until @alexanderjoe said it.
Please or to participate in this conversation.