I am testing whether a successful log in happens or not. For that I am checking,
For that my controller
looks like this
public function loginPost(){
if (Auth::attempt(array(
'email' => Input::get('email'),
'password' => Input::get('password')
))){
return Redirect::intended(route('dashboard'));
}
return Redirect::route('login')
->withInput()
->with('errorMessage', 'Failed');
}
And my test
looks like this
public function testLoginSuccess(){
$input = [
'email' => '[email protected]',
'password' => 'computer'
];
Input::replace($input);
Auth::shouldReceive('attempt')
->with($input)
->once()
->andReturn(true);
$this->call('POST', 'login', $input);
$this->assertRedirectedToRoute('dashboard');
}
Although this works in browser. But while testing, it fails with the message:
BadMethodCallException: Method Mockery_0_Illuminate_Auth_AuthManager::check() does not exist on this mock object
You didn't show the definition of your route, but I'm assuming your login
route is protected by the guest
before filter. This filter uses Auth::check()
before dispatching to the route.
In your test, when you call Auth::shouldReceive()
, that makes the Auth
facade point to a mocked instance. Since you did not define an expectation on the mocked instance for the check()
method, you're getting an error.
The easiest solution would be to go ahead and mock the Auth::check()
method as well, and have it return false
(to emulate visiting the route while not logged in).
public function testLoginSuccess() {
$input = [
'email' => '[email protected]',
'password' => 'computer'
];
Input::replace($input);
// Tell Auth we're not logged in.
Auth::shouldReceive('check')
->once()
->andReturn(false);
Auth::shouldReceive('attempt')
->with($input)
->once()
->andReturn(true);
$this->call('POST', 'login', $input);
$this->assertRedirectedToRoute('dashboard');
}
You could also write a second test with Auth::check()
mocked to return true
in order to test what happens when you visit your login route while already logged in.
In my opinion, this is a functional test not a unit test. There is absolutely no need for you keep mocking classes. You need to write a functional test for this.
If i had to do it, i would do something like this:
http://localhost/home
So your test code in Laravel 4.2 will be something like this:
// Update the following code accordingly for your app.
$credentials = array(
'email' => '[email protected]',
'password' => 'johndoe',
'csrf_token' => csrf_token()
);
$this->withInput( $credentials )
->requestAction('POST', 'UserController@postLogin');
$this->assertRedirection( URL::action('HomeController@getIndex') );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With