Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

zaster's avatar

Manual test works but not the Automated test

<?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

0 likes
29 replies
Tray2's avatar

A good tip is to use

$this->withoutExceptionHandling();

When in doubt why it isn't working. Just put it in above the user creation.

1 like
martinbean's avatar

@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…

1 like
zaster's avatar

@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.
Tray2's avatar

403 means forbidden. So most likely the user you are creating isn't a "provider" user.

zaster's avatar

@tray2

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

lemmon's avatar

@zaster

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.
zaster's avatar

@lemmon

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()
lemmon's avatar

@zaster

As @tray2 said

403 means forbidden. So most likely the user you are creating isn't a "provider" user.

So That user does not have authorization to use that route.

lemmon's avatar

@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

zaster's avatar

@lemmon

//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,
    ];

lemmon's avatar

@zaster I would compare my middleware for customer, admin, employee with the provider middleware something is different.

zaster's avatar

@lemmon

<?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);
    }
}
Tray2's avatar

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.

zaster's avatar

@lemmon

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);
    }
}

zaster's avatar

@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);	

lemmon's avatar

@zaster try doing what @tray2 suggested, change the 403 to 401 and if you get a 401 then the user is not getting created as 'is_provider' somehow.

lemmon's avatar

@zaster

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?

1 like
alexanderjoe's avatar
Level 9

Do you have is_provider in the fillable array on the User model?

2 likes
zaster's avatar

@alexanderjoe

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**
    ];
1 like

Please or to participate in this conversation.