login() rather than actingAs(): actingAs() only sets // an in-memory user on the guard object, it never writes to the session // — so it cannot tell session()->invalidate() and session()->regenerate() // apart. login() does the same session write a real sign-in performs. $operator = Operator::factory()->role('Owner')->create(); $customer = User::factory()->create(); Auth::guard('web')->login($customer); Auth::guard('operator')->login($operator); $this->post(route('admin.logout'))->assertRedirect(route('admin.login')); // Auth::guard('web') is still the SAME cached guard instance from the // login() call above — its check() would say "authenticated" from its // own in-memory $user property regardless of what happened to the // session, which is exactly the blind spot that would make this // assertion pass whether the fix is there or not. forgetGuards() drops // that cache, forcing the next guard() call to rebuild from the CURRENT // session data — the same thing a genuinely new request would do. Auth::forgetGuards(); expect(Auth::guard('operator')->check())->toBeFalse() ->and(Auth::guard('web')->check())->toBeTrue() ->and(Auth::guard('web')->id())->toBe($customer->id); });