认证测试运行奇怪

时间:2014-11-04 17:26:57

标签: testing laravel phpunit mockery laravel-testing

我刚刚尝试为Auth编写一个简单的测试:

use Mockery as m;

...

public function testHomeWhenUserIsNotAuthenticatedThenRedirectToWelcome() {
    $auth = m::mock('Illuminate\Auth\AuthManager');
    $auth->shouldReceive('guest')->once()->andReturn(true);

    $this->call('GET', '/');

    $this->assertRedirectedToRoute('general.welcome');
}

public function testHomeWhenUserIsAuthenticatedThenRedirectToDashboard() {
    $auth = m::mock('Illuminate\Auth\AuthManager');
    $auth->shouldReceive('guest')->once()->andReturn(false);

    $this->call('GET', '/');

    $this->assertRedirectedToRoute('dashboard.overview');
}

这是代码:

public function getHome() {
    if(Auth::guest()) {
        return Redirect::route('general.welcome');
    }
    return Redirect::route('dashboard.overview');
}

当我跑步时,我遇到以下错误:

EF.....

Time: 265 ms, Memory: 13.00Mb

There was 1 error:

1) PagesControllerTest::testHomeWhenUserIsNotAuthenticatedThenRedirectToWelcome
Mockery\Exception\InvalidCountException: Method guest() from Mockery_0_Illuminate_Auth_AuthManager should be called
 exactly 1 times but called 0 times.

—

There was 1 failure:

1) PagesControllerTest::testHomeWhenUserIsAuthenticatedThenRedirectToDashboard
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'http://localhost/dashboard/overview'
+'http://localhost/welcome'

我的问题是:

  1. 两个类似的测试用例,但为什么错误输出有所不同?第一个模拟Auth::guest()未被调用,而第二个似乎被调用。

  2. 在第二个测试用例中,为什么会失败?

  3. 有没有办法为我上面的代码编写更好的测试?甚至更好的代码来测试。

  4. 以上测试用例,我使用Mockery来模拟AuthManager,但如果我使用了外观Auth::shoudReceive()->once()->andReturn(),那么它最终会起作用。这里MockeryAuth::mock外观之间是否有任何不同?

  5. 感谢。

1 个答案:

答案 0 :(得分:2)

您实际上正在模拟Illuminate\Auth\AuthManager的新实例,而不是访问Auth正在使用的function getHome()外观。因此,你的模拟实例永远不会被调用。 (标准免责声明未测试以下代码。)

试试这个:

public function testHomeWhenUserIsNotAuthenticatedThenRedirectToWelcome() {
    Auth::shouldReceive('guest')->once()->andReturn(true);

    $this->call('GET', '/');

    $this->assertRedirectedToRoute('general.welcome');
}

public function testHomeWhenUserIsAuthenticatedThenRedirectToDashboard() {     

    Auth::shouldReceive('guest')->once()->andReturn(false);

    $this->call('GET', '/');

    $this->assertRedirectedToRoute('dashboard.overview');
}

如果你查看Illuminate\Support\Facades\Facade,你会发现它会照顾你。如果你真的想按照你的方式去做(创建一个Auth的模拟实例的实例),你必须以某种方式将它注入到被测试的代码中。我相信它可以用这样的东西来完成,假设你从laravel提供的TestCase类扩展:

public function testHomeWhenUserIsNotAuthenticatedThenRedirectToWelcome() {
    $this->app['auth'] = $auth = m::mock('Illuminate\Auth\AuthManager');
    // above line will swap out the 'auth' facade with your facade.

    $auth->shouldReceive('guest')->once()->andReturn(true);

    $this->call('GET', '/');

    $this->assertRedirectedToRoute('general.welcome');
}