2014-11-04 53 views
0

我只是试着写一个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立面有什么不同吗?

谢谢。

回答

2

您实际上正在嘲笑Illuminate\Auth\AuthManager的新实例,而不是访问您的function getHome()正在使用的Auth外观。 Ergo,你的模拟实例永远不会被调用。 (标准免责声明,没有一个下面的代码的测试。)

试试这个:

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

我刚刚误认为是没有创建模拟对象'$这个 - > APP->实例( )'。 :)无论如何, – 2014-11-19 16:00:18

+0

还要确保如果你有' - >中间件('auth')'设置路径,你将这个特征添加到你的测试中'Illuminate \ Foundation \ Testing \ WithoutMiddleware' – 2016-10-12 19:21:06