Unit testing Laravel 4 Auth extension

Laravel 4 is a great framework, it has all sorts of good stuff like IoC, automatic injection of Models into Controllers based on routes.

However, if you try and unit test a custom extension to the Auth package, you will find that some of the tests fail.

Here’s the code:

/**
 * ----------------------------------------------------
 * Extend the Auth functionality
 * to allow admin user to switch users
 * ----------------------------------------------------
 */
Auth::extend('eloquent', function($app) {
    $hasher = new \Illuminate\Hashing\BcryptHasher();
    $user_class = '\Repository\User\EloquentUserRepository';
    $provider = new \Illuminate\Auth\EloquentUserProvider($hasher, $user_class);
    return new CustomAuthGuard($provider,  App::make('session.store'));
});

This works fine if you test it by clicking through but this unit test failed

public function testLoginAsUser()
{
     $login_user = EloquentUserRepository::find($this->admin_user_id);
     $this->be($login_user);
     $this->assertEquals(Auth::user()->id, $this->admin_user_id);
}

The problem turned out to be in the way that the ‘be’ function set the logged in user

public function be(UserInterface $user, $driver = null)
{
     $this->app['auth']->driver($driver)->setUser($user);
}

The Auth::user() function finds the user by checking the session for the user id and then querying that user against the UserProvider. It relies on a session key ‘login_’+md5(class name). In testing, this is not being picked up. The solution I found was to use this instead.

public function testLoginAsUser()
{
     $login_user = EloquentUserRepository::find($this->admin_user_id);
     Auth::login($login_user);
     $this->assertEquals(Auth::user()->id, $this->admin_user_id);
}