我正在尝试通过为一些遗留代码编写单元测试(并在此过程中对其进行更新)来清理现有应用程序。我重写了许多库,我真的很喜欢 TDD 方法。然而,现在是时候继续测试一些控制器了,我在第一组测试中遇到了问题。我正在遵循 Jeffery Way 的Laravel Testing Decoded中的解释。
这里的目标是测试我的登录路线:http://my-development-server/login
. 代码应该是这样工作的:首先,检查是否有人已经登录 - 如果是,将他们重定向到仪表板(应用程序的主页)。否则,呈现登录页面。很直接。
以下是涉及的路线:
Route::get('login', array(
'as' => 'login',
'uses' => 'MyApp\Controllers\AccountController@getLogin',
));
Route::get('/', array(
'as' => 'dashboard',
'uses' => 'MyApp\Controllers\DashboardController@showDashboard',
'before' => 'acl:dashboard.view',
));
这是AccountController::getLogin
方法:
public function getLogin()
{
// Are we logged in?
if (\Sentry::check())
return Redirect::route('dashboard');
// Show the page.
return View::make('account.login');
}
我正在使用该Sentry
库进行用户身份验证。
这是我的第一个测试:
class AccountControllerTest extends TestCase {
public function tearDown()
{
Mockery::close();
}
public function test_login_alreadyLoggedIn()
{
// arrange
//
\Sentry::shouldReceive("check")
->once()
->andReturn(true);
// act
//
$response = $this->call("GET", "/login");
// assert
//
$this->assertRedirectedToRoute("dashboard");
}
}
此测试模拟“用户在已经登录时尝试登录”的情况。check
返回 true(已经登录)并且用户被重定向到名为dashboard
. 它运行良好,测试通过。
接下来,我添加一个新的测试,以测试“没有人登录时用户尝试登录”的情况。这是该测试的代码:
public function test_login_notLoggedIn()
{
// arrange
//
\Sentry::shouldReceive("getUser")
->twice()
->andReturn(null);
\Sentry::shouldReceive("check")
->once()
->andReturn(false);
// act
//
$response = $this->client->request("GET", "/login");
// assert
//
$h2 = $response->filter("h2");
$this->assertEquals("Please sign in", $h2->text());
}
当我运行这个测试时,第一个测试通过了,但我NotFoundHttpException
在第二个测试方法中得到了一个。
这个问题有几个奇怪的地方:
如果我注释掉第一个测试方法 (
test_login_alreadyLoggedIn
),则第二个测试通过。如果我颠倒两个测试方法的顺序,则
test_login_notLoggedIn
通过和test_login_alreadyLoggedIn
失败(即类中的第一个方法通过,第二个失败)。
在我看来,这像是某种配置问题——在第一次测试(通过)之后,有些东西搞砸了,它无法在第二次测试中发出请求——但我不知所措。我已经多次翻阅这本书和谷歌,但找不到任何我缺少的配置的参考。
有什么建议么?