2014-04-17 173 views
2

轉發:我對單元測試,嘲笑,ioc容器等是相當新的。因此,可能有一個簡單的答案,但我在我的智慧結局,因爲我可以沒有看到它。Laravel控制器單元測試嘲笑模型不叫

我想測試一個控制器的行爲。該動作應該在模型上調用一個函數,返回一個模型。在測試中,我嘲笑模型,將其綁定到IOC容器。我通過它的構造函數將依賴注入到控制器中。然而,不知何故,模擬並沒有被發現和調用,而是調用了該模型的實時版本。 (我可以說,正在生成日誌。)

首先,我的單元測試。創建模擬,告訴它期望一個函數,將其添加到ioc容器,調用路由。

public function testHash(){ 
    $hash = Mockery::mock('HashLogin'); 
    $hash->shouldReceive('checkHash')->once(); 

    $this->app->instance('HashLogin', $hash); 

    $this->call('GET', 'login/hash/c3e144adfe8133343b37d0d95f987d87b2d87a24'); 
} 

其次,我的控制器構造函數的依賴注入。

public function __construct(User $user, HashLogin $hashlogin){ 
    $this->user = $user; 
    $this->hashlogin = $hashlogin; 
    $this->ip_direct = array_key_exists("REMOTE_ADDR",$_SERVER) ? $_SERVER["REMOTE_ADDR"] : null; 
    $this->ip_elb = array_key_exists("HTTP_X_FORWARDED_FOR",$_SERVER) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : null; 

    $this->beforeFilter(function() 
    { 
     if(Auth::check()){return Redirect::to('/');} 
    }); 
} 

然後我的控制器方法。

public function getHash($code){ 
    $hash = $this->hashlogin->checkHash($code); 
    if(!$hash){ 
     return $this->badLogin('Invalid Login'); 
    } 
    $user = $this->user->getFromLegacy($hash->getLegacyUser()); 
    $hash->cleanup(); 
    $this->login($user); 
    return Redirect::intended('/'); 
} 

控制器方法被調用正確,但它似乎沒有看到我的模擬,所以它調用實際模型的功能。這導致模擬的期望失敗,並且對數據庫進行檢查,這是不可取的。

預先感謝您! -Wally

編輯:我也在另一個測試中得到同樣的問題,雖然這一個使用Laravel的內置在外牆。

測試:

public function testLoginSuccessfulWithAuthTrue(){ 
    Input::shouldReceive('get')->with('username')->once()->andReturn('user'); 
    Input::shouldReceive('get')->with('password')->once()->andReturn('1234'); 
    Auth::shouldReceive('attempt')->once()->andReturn(true); 
    $user = Mockery::mock('User'); 
    $user->shouldReceive('buildRBAC')->once(); 
    Auth::shouldReceive('user')->once()->andReturn($user); 

    $this->call('POST', 'login'); 

    $this->assertRedirectedToRoute('index'); 
} 

在控制器方法:

public function postIndex(){ 
    $username = Input::get("username"); 
    $pass = Input::get('password'); 
    if(Auth::attempt(array('username' => $username, 'password' => $pass))){ 
     Auth::user()->buildRBAC(); 
    }else{ 
     $user = $this->user->checkForLegacyUser($username); 
     if($user){ 
      $this->login($user); 
     }else{ 
      return Redirect::back()->withInput()->with('error', "Invalid credentials."); 
     } 
    } 
    return Redirect::intended('/'); 
} 

我收到的錯誤:

Mockery\Exception\InvalidCountException: Method get("username") from Mockery_5_Illuminate_Http_Request should be called exactly 1 times but called 0 times." 

同樣,我知道方法正確調用,它似乎嘲笑沒有被使用。

再次感謝您的任何建議。

編輯2

解決了它。我曾嘗試在一個地方或另一個地方使用命名空間,但顯然Mockery :: mock和app-> instance()都需要完全命名空間名稱。這個問題在其他測試中並沒有發生,所以我甚至沒有考慮過它。我希望這可以幫助別人,因爲這一段時間讓我感到頭痛。

相關代碼固定:

$hash = Mockery::mock('App\Models\Eloquent\HashLogin'); 
... 
$this->app->instance('App\Models\Eloquent\HashLogin', $hash); 

我不能回答我自己的,由於代表限制6小時的問題,但在那個時候這樣做。

-Wally

回答

3

解決了它。我曾嘗試在一個地方或另一個地方玩名稱空間,但顯然Mockery::mockapp->instance()都需要完全名稱空間名稱。這個問題在其他測試中並沒有發生,所以我甚至沒有考慮過它。我希望這可以幫助別人,因爲這一段時間讓我感到頭痛。

相關代碼固定:

$hash = Mockery::mock('App\Models\Eloquent\HashLogin'); 
$this->app->instance('App\Models\Eloquent\HashLogin', $hash);