我正在测试是否成功登录。为此,我正在检查,
- 如果已成功登录
- 应用程序应重定向到仪表板
为此,我的controller
看起来像这样
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');
}
我的test
看起来像这样
public function testLoginSuccess(){
$input = [
'email' => 'xyz@gmail.com',
'password' => 'computer'
];
Input::replace($input);
Auth::shouldReceive('attempt')
->with($input)
->once()
->andReturn(true);
$this->call('POST', 'login', $input);
$this->assertRedirectedToRoute('dashboard');
}
虽然这在浏览器中有效。但在测试时,它失败并显示以下消息:
BadMethodCallException:方法 Mockery_0_Illuminate_Auth_AuthManager::check() 在此模拟对象上不存在
您没有显示路由的定义,但我假设您的login
路由受guest
before过滤器的保护。此筛选器在调度到路由之前使用Auth::check()
。
在您的测试中,当您调用 Auth::shouldReceive()
时,会使Auth
外观指向模拟实例。由于您没有为 check()
方法定义对模拟实例的期望,因此您会收到错误。
最简单的解决方案是继续模拟Auth::check()
方法,并让它返回false
(以模拟在未登录时访问路由)。
public function testLoginSuccess() {
$input = [
'email' => 'xyz@gmail.com',
'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');
}
您还可以编写第二个测试,模拟Auth::check()
以返回true
,以测试当您在已登录的情况下访问登录路由时会发生什么。
在我看来,这是一个功能测试,而不是单元测试。你绝对没有必要继续嘲笑课程。您需要为此编写一个功能测试。
如果我必须这样做,我会做这样的事情:
- 使用用户名、密码、csrf_token等向登录路由发送帖子请求。
- 断言该页面被重定向到链接,假设:
http://localhost/home
所以你在Laravel 4.2中的测试代码将是这样的:
// Update the following code accordingly for your app.
$credentials = array(
'email' => 'john@example.com',
'password' => 'johndoe',
'csrf_token' => csrf_token()
);
$this->withInput( $credentials )
->requestAction('POST', 'UserController@postLogin');
$this->assertRedirection( URL::action('HomeController@getIndex') );
也许,这个堆栈溢出线程可能会有所帮助。
顺便说一句:我同意@Raza Mehdi的观点。
我认为从高层次测试登录功能,测试我们的实际代码,而不是模拟Auth
对象(我们不拥有的类型)。
- 调用登录路由,传递用户凭据。
- 断言状态为"正常"。
- 断言用户被重定向到仪表板。
在代码中:
$input = [...];
$this->call('POST', 'login', $input);
$this->assertResponseStatus(200);
$this->assertRedirectedToRoute('dashboard');