Search code examples
phplaravel-5phpunit

Feature test actingas effects all guards?


I have two different user objects in my application, one App\User and one App\Admin. For both, I have different guards for authentication.

My default guard is the web guard for model App\User and I also have an admin guard for the model App\Admin.

For example, this code

  $admin = factory(\App\Admin::class)->make();
  \Auth::guard('admin')->login($admin);

  dd([\Auth::check(), \Auth::guard('admin')->check()]);

returns

[false, true]

as expected.

However, inside my feature test I am doing this:

$admin = factory(\App\Admin::class)->make();
$response = $this->actingAs($admin, 'admin')
                 ->get('/admin');
dd([\Auth::check(), \Auth::guard('admin')->check()]);

this returns for some reason

[true, true]

This causes all kind of errors (For example I have a log middleware for normal users, and trying to store the admin as normal user throws foreign_key exceptions etc.).

Why is actingAs enabling both guards? Is it a bug in Laravel 5.6 or am I doing something wrong?


Solution

  • When you call actingAs method, Laravel changes the default guard to admin internally (In this case).

    Please use the code below

    $defaultGuard = config('auth.defaults.guard');
    
    $admin = factory(\App\Admin::class)->make();
    $this->actingAs($admin, 'admin');
    \Auth::shouldUse($defaultGuard);
    
    $response = $this->get('/admin');
    
    dd([\Auth::check(), \Auth::guard('admin')->check()]);
    

    Also you can extract a method actingAsAdmin in the TestCase class, so that you can reuse the function.

    public function actingAsAdmin($admin) {
        $defaultGuard = config('auth.defaults.guard');
        $this->actingAs($admin, 'admin');
        \Auth::shouldUse($defaultGuard);
    
        return $this;
    }
    

    And call this function like below.

    $admin = factory(\App\Admin::class)->make();
    $response = $this->actingAsAdmin($admin)->get('/admin');
    dd([\Auth::check(), \Auth::guard('admin')->check()]);