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); }