I recently found myself writing a test where I needed to test a macro applied to the Request object in Laravel. But I needed the user to be 'authenticated'.
Here's how to mock authenticated users in Laravel's Request
object.
First, here's the macro I added to the Request
object, which returns the user's currently associated team. This isn't important, but some context may help.
Request::macro('team', function () {
return $this->user()?->currentTeam;
});
If we were to write a test like this, it wouldn't work:
it('can access the current team through the request', function () {
$user = User::factory()->create();
expect(request()->team())->toBeInstanceOf(Team::class);
});
We don't want to (and can't) use actingAs
here to authenticate the user. Nor can we use auth()->login($user)
.
So, the solution is to set the user resolver like this:
it('can access the current team through the request', function () {
$user = User::factory()->create();
request()->setUserResolver(function () use ($user) {
return $user;
});
expect(request()->team())->toBeInstanceOf(Team::class);
});
Now, when the macro I created for Request
invokes user()
, it'll return the user defined in the test.
You can further shorten this down, too, with a short arrow function:
it('can access the current team through the request', function () {
$user = User::factory()->create();
request()->setUserResolver(fn () => $user);
expect(request()->team())->toBeInstanceOf(Team::class);
});
That's it. If you need to assume an authenticated user in tests that don't make an HTTP request, override the user resolver with setUserResolver
.