【问题标题】:Authentication test running strange身份验证测试运行异常
【发布时间】:2014-12-31 16:57:59
【问题描述】:

我刚刚尝试为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门面有什么不同吗?

谢谢。

【问题讨论】:

    标签: testing laravel phpunit mockery laravel-testing


    【解决方案1】:

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

    试试这个:

    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');
    }
    

    【讨论】:

    • 我只是误认为没有创建模拟对象$this->app->instance()。无论如何谢谢:)
    • 还要确保如果您在路由上设置了->middleware('auth'),则将此特征添加到您的测试Illuminate\Foundation\Testing\WithoutMiddleware
    猜你喜欢
    • 2014-09-15
    • 2018-12-10
    • 2012-01-07
    • 2020-01-01
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 2015-06-04
    • 2013-12-29
    相关资源
    最近更新 更多