After finally getting my stupid simple test to pass, I have a feeling that I'm not doing it correctly.
I have a SessionsController, that is responsible for displaying a login page and logging a user in.
I have decided not to use facades so that I wouldn't have to extend Laravel's TestCase and take a performance hit on my unit tests. Therefore, I have injected all the dependencies through the controller, like so -
SessionsController - Constructor
public function __construct(UserRepositoryInterface $user,
AuthManager $auth,
Redirector $redirect,
Environment $view )
{
$this->user = $user;
$this->auth = $auth;
$this->redirect = $redirect;
$this->view = $view;
}
I have done the necessary declaring of variables and using the namespaces, which I'm not going to include here as its unnecessary.
the create method detects if a user is authorized, if they are then I redirect them to the home page, otherwise they are displayed the login form.
SessionsController - Create
public function create()
{
if ($this->auth->user()) return $this->redirect->to('/');
return $this->view->make('sessions.login');
}
Now for the testing, I'm brand new to it, so bear with me.
SessionsControllerTest
class SessionsControllerTest extends PHPUnit_Framework_TestCase {
public function tearDown()
{
Mockery::close();
}
public function test_logged_in_user_cannot_see_login_page()
{
# Arrange (Create mocked versions of dependencies)
$user = Mockery::mock('GlennRepositoriesUserUserRepositoryInterface');
$authorizedUser = Mockery::mock('IlluminateAuthAuthManager');
$authorizedUser->shouldReceive('user')->once()->andReturn(true);
$redirect = Mockery::mock('IlluminateRoutingRedirector');
$redirect->shouldReceive('to')->once()->andReturn('redirected to home');
$view = Mockery::mock('IlluminateViewEnvironment');
# Act (Attempt to go to login page)
$session = new SessionsController($user, $authorizedUser, $redirect, $view);
$result = $session->create();
# Assert (Return to home page)
}
}
This all passes, but I don't want to have to declare all of these mocked dependencies for each test that I write in my SessionsControllerTest. Is there a way to declare these mocked dependencies once in say a constructor? and then call them by there variables for mocking?
You can use the
setUp
method to declare any dependencies that are global for the entire test class. It's similar to thetearDown
method you're currently using:However that won't work if your set up for the mock differs between tests. For this case you can use a helper method:
Then when you need the auth mock you can just call
getAuthMock
. This can greatly simplify your tests.However
I don't think you're testing your controller correctly. You shouldn't instantiate the controller object yourself, instead you should utilize the
call
method which exists in Laravel'sTestCase
class. Try checking out this article about testing Laravel Controllers by Jeffrey Way. I think you're looking to do something more along the lines of this in your test: