2013-10-18 27 views
-1

我正在爲我的一個控制器編寫CakePHP單元測試。控制器有幾個調用AuthComponent::user()方法,讀取當前登錄用戶的數據。有3個用途:在CakePHP中嘲諷authed用戶

  • AuthComponent::user()(無參數,可以獲取整個陣列)
  • AuthComponent::user('id')(提取的用戶ID)
  • AuthComponent::user('name')(獲取的用戶名)

我已經嘗試了兩種在我的測試中嘲諷AuthComponent的方法:

// Mock the Controller and the Components 
$this->controller = $this->generate('Accounts', array(
    'components' => array(
     'Session', 'Auth' => array('user'), 'Acl' 
    ) 
)); 

// Method 1, write the entire user array 
$this->controller->Auth->staticExpects($this->any())->method('user') 
    ->will($this->returnValue(array(
     'id' => 2, 
     'username' => 'admin', 
     'group_id' => 1 
    ))); 

// Method 2, specifically mock the AuthComponent::user('id') method 
$this->controller->Auth->staticExpects($this->any())->method('user') 
    ->with('id') 
    ->will($this->returnValue(2)); 

Thes但是,方法不適用於我。方法1似乎沒有做任何事情,我的控制器中使用當前登錄用戶的id的保存操作返回null,所以這個值沒有被正確設置/獲得。

方法2似乎工作,但過於寬泛,它也試圖將自身綁定到AuthComponent::user()調用(在一個沒有PARAMS),它失敗,出現錯誤:

Expectation failed for method name is equal to when invoked zero or more times Parameter 0 for invocation AuthComponent::user(null) does not match expected value. Failed asserting that null matches expected 'id'.

我怎樣才能得到正確的嘲笑AuthComponent所以可以獲得所有的字段/變量?

回答

2

這就是我的做法。請注意,在此代碼中,我使用'Employee'作爲我的用戶模型,但它應該很容易更改。

我有一個AppControllerTest.php超類,它爲'user'方法返回一個回調。回調處理帶或不帶參數的情況。 _generateMockWithAuthUserId就是你以後的事情 - 但是全部閱讀。還有一些值得注意的事情,比如testPlaceholder。這是我的全班同學:

<?php 
App::uses('Employee', 'Model'); 

/** 
* EmployeeNotesController Test Case 
* Holds common Fixture ID's and mocks for controllers 
*/ 
class AppControllerTest extends ControllerTestCase { 

    public $authUserId; 

    public $authUser; 

/** 
* setUp method 
* 
* @return void 
*/ 
    public function setUp() { 
     parent::setUp(); 
     $this->Employee = ClassRegistry::init('Employee'); 
    } 

/** 
* tearDown method 
* 
* @return void 
*/ 
    public function tearDown() { 
     unset($this->Employee); 
     parent::tearDown(); 
    } 

    public function testPlaceholder() { 
     // This just here so we don't get "Failed - no tests found in class AppControllerTest" 
     $this->assertTrue(true); 
    } 

    protected function _generateMockWithAuthUserId($contollerName, $employeeId) { 
     $this->authUserId = $employeeId; 
     $this->authUser = $this->Employee->findById($this->authUserId); 
     $this->controller = $this->generate($contollerName, array(
      'methods' => array(
       '_tryRememberMeLogin', 
       '_checkSignUpProgress' 
      ), 
      'components' => array(
       'Auth' => array(
        'user', 
        'loggedIn', 
       ), 
       'Security' => array(
        '_validateCsrf', 
       ), 
       'Session', 
      ) 
     )); 

     $this->controller->Auth 
      ->expects($this->any()) 
      ->method('loggedIn') 
      ->will($this->returnValue(true)); 

     $this->controller->Auth 
      ->staticExpects($this->any()) 
      ->method('user') 
      ->will($this->returnCallback(array($this, 'authUserCallback'))); 
    } 

    public function authUserCallback($param) { 
     if (empty($param)) { 
      return $this->authUser['Employee']; 
     } else { 
      return $this->authUser['Employee'][$param]; 
     } 
    } 
} 

然後,我的控制器測試用例從該類繼承:

require_once dirname(__FILE__) . DS . 'AppControllerTest.php'; 
class EmployeeNotesControllerTestCase extends AppControllerTest { 
    // Tests go here 

而當你想嘲笑AUTH組件的測試,你叫

$this->_generateMockWithAuthUserId('EmployeeNotes', $authUserId); 

其中'EmployeeNotes'將是您的控制器的名稱,並且$ authUserId是用戶在測試數據庫中的ID。

+0

謝謝,這讓我度過了煩人的錯誤,並且是一個很好的構造,可以快速模擬Auth對所有測試的感受。在開始工作之前(由於某種原因靜態方法一直返回null),我最終在控制器中用'$ this-> Auth-> user'調用了靜態'AuthComponent :: user'調用。 – Oldskool