【问题标题】:Unable to run multiple controller tests in Laravel无法在 Laravel 中运行多个控制器测试
【发布时间】:2014-06-18 13:09:33
【问题描述】:

我正在尝试通过为一些遗留代码编写单元测试(并在此过程中对其进行更新)来清理现有应用程序。我重写了许多库,我真的很喜欢 TDD 方法。然而,现在是时候继续测试一些控制器了,我在第一组测试中遇到了问题。我正在遵循 Jeffery Way 的 Laravel 测试解码 中的解释。

这里的目标是测试我的登录路径: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

关于这个问题有几个奇怪的地方:

  1. 如果我注释掉第一个测试方法 (test_login_alreadyLoggedIn),则第二个测试通过。

  2. 如果我颠倒两个测试方法的顺序,test_login_notLoggedIn 通过,test_login_alreadyLoggedIn 失败(即类中的第一个方法通过,第二个失败)。

在我看来,这像是某种配置问题——在第一次测试(通过)之后,有些东西搞砸了,它无法在第二次测试中发出请求——但我不知所措。我已经多次翻阅这本书和谷歌,但找不到任何我缺少的配置的参考。

有什么建议吗?

【问题讨论】:

    标签: php unit-testing laravel phpunit mockery


    【解决方案1】:

    您可以通过将require_once() 替换为require() 来解决此问题

    【讨论】:

      【解决方案2】:

      对于将来可能遇到此问题的任何人...

      这是由我的 routes.php 文件的问题引起的。特别是,我将路由组织成一组文件:

      1. accounts.php - 包含与“帐户”功能相关的路由

      2. admin.php - 包含与“管理”功能相关的路由

      3. 等等……

      这些文件随后被包含在我的routes.php 文件中,并带有require_once。这对我的应用程序来说很好,但由于某种原因,在测试期间路由没有正确加载。解决方案是将我的路线移回routes.php 文件,直到找到更好的方法来组织它们。

      【讨论】:

      • 谢谢,刚刚花了 20 分钟调试同样的问题!在 routes.php 中将 require_once() 更改为 require() 修复了测试问题,到目前为止我还没有注意到其他副作用。
      • 为什么这是个问题?有人能解释一下这背后的逻辑吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      相关资源
      最近更新 更多