Skip to content

Documentation on mocking users in feature and unit tests #467

Open
@joshembling

Description

@joshembling

Checklist

Description

I am really struggling to figure out how to simply mock a user so that I can test web and api routes.

I have a bundle of routes wrapped in the auth0 middleware for SSO. All of this works as expected.

Route::middleware('auth0.authenticate')->group(function (): void { // ...

However, in my feature and unit every single request I make is a 302 redirect. To state the obvious, when I take the routes out of this middleware, the requests work as expected.

This is my User model:

class User extends Model implements AuthenticatableContract, AuthorizableContract
{
    use Authenticatable;
    use Authorizable;
    use HasApiTokens;
    use HasFactory;
    use Notifiable;

I have tried the following in my tests:

use Auth0\Laravel\Traits\Impersonate;

class ControllerTest extends TestCase
{
    use WithFaker, Impersonate;
  
    public function test_impersonation_as_session_user()
    {
        $user = User::factory()->create();
    
        $cred = CredentialEntity::create($user);
        Auth::login($cred);
    
        // Impersonate the user
        $this->impersonate($cred);
    
        // Perform some action.
        $response = $this->get('/');
        $response->assertStatus(200); // 302
    }

    public function test_impersonation_as_session_user()
    {
        // Create a mock credential.
        $mockCredential = $this->createMock(CredentialEntityContract::class);
        $mockCredential->method('getUser')->willReturn(new ImposterUser([
            'id' => 1,
            'name' => 'Test User',
            'email' => '[email protected]',
        ]));

        /** @var CredentialEntityContract $mockCredential */
        $this->impersonate($mockCredential, \Auth0\Laravel\Guards\GuardContract::SOURCE_SESSION);

        // Assert the user is authenticated.
        $this->assertAuthenticated();
        $this->assertEquals(auth()->user()->id, 1);

        // Perform some action.
        $response = $this->get('/');
        $response->assertStatus(200); // 302
    }
}

This is the only thing I've been able to get to work, but this is not correct:

    public function test_impersonation_as_session_user()
    {
        Route::middleware([])->group(function () {
            Route::get('/', [DashboardController::class, 'dashboard'])->name('dashboard');
        });

        $user = User::factory()->create();

        $this->actingAs($user);

        // Perform some action.
        $response = $this->get('/');
        $response->assertStatus(200); // 200
    }

Please can someone shed some light on how this is supposed to work properly in phpunit and/or pest.

I don't mind writing some documentation if someone can contribute a working answer. Thank you 🙏

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions