Feature test actingas effects all guards?
Asked Answered
C

2

5

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?

Cale answered 12/9, 2019 at 5:28 Comment(2)
Have you ever solved this? I have the same issue, no matter what guard I specify.Massage
@ParanoidAndroid yes I solved it as explained in the checked answer. Does this not work for you?Cale
G
9

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()]);
Gautama answered 12/9, 2019 at 6:23 Comment(2)
The second solution seems nice, but \Auth::shouldUse does not change the default guard outside the function. If you output config('auth.defaults.guard') after you called actingAsAdmin then it will be the-non default guard.Cale
I noticed it because when creating two get responses both using actingAsAdminCale
K
0

I was calling actingAs() in my setup method, but needed to use a different guard for one of my tests. All I needed to do in the test was:

Auth::logout();
$this->actingAs($admin, "admin");

The key was specifying the guard in the function call, it wouldn't work otherwise.

Kosey answered 11/1 at 16:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.