2009-08-07 38 views
5

我正在用CakePHP(剛剛發佈1.2.4),使用SimpleTest 1.0.1編寫一個新的應用程序。我已閱讀Cookbook的相關章節,在Bakery上進行了搜索,並閱讀了Mark Story在控制器測試中的帖子(hard waywith mocks)。CakePHP控制器的真實世界測試?

不幸的是,這些都沒有提到非平凡控制器的真實測試。很多應用程序都將登錄後的網站區域放在後面,但我無法弄清楚如何測試以下簡單場景:

  • 訪客受保護的頁面重定向?
  • 有效憑證設置預期會話變量?
  • 無效憑證重新顯示登錄頁面並顯示錯誤消息?

下面的控制器和測試不工作,因爲我認爲他們會。這兩個斷言失敗,我也得到一個PHP錯誤:

失敗 [NULL]不應該在[... /應用/測試/例/控制器/ users_controller.test.php線79] 空... /app/tests/cases/controllers/users_controller.test.php - >的UsersControllerTest - > TESTLOGIN

FAILED如[NULL]不匹配 等於期望失敗[整數:1] [... /應用/測試/cases/controllers/users_controller.test.php line 80] .../app/tests/cases/controllers/users_controller.test.php - > UsersControllerTest - > testLogin

錯誤 意外的PHP錯誤[未定義的索引:操作]嚴重性[E_NOTICE]在[.../cake/libs/controller/components/auth.php 266行中] .../app/tests/cases/controllers/users_controller.test .PHP - >的UsersControllerTest - > TESTLOGIN

這裏是控制器(烤加上馬克故事的 「辛苦」 的測試方法):

class UsersController extends AppController 
{ 
    var $name = 'Users'; 
    var $helpers = array('Html', 'Form'); 
    var $components = array('Auth'); 

    function login() 
    { 
    } 

    function logout() 
    { 
    $this->redirect($this->Auth->logout()); 
    } 

    function index() 
    { 
    $this->set('users', $this->paginate()); 
    } 

    function view($id = null) 
    { 
    if (!$id) 
    { 
     $this->Session->setFlash(__('Invalid User.', true)); 
     $this->redirect(array('action'=>'index')); 
    } 
    $this->set('user', $this->User->read(null, $id)); 
    } 

    function add() 
    { 
    if (!empty($this->data)) 
    { 
     $this->User->create(); 
     if ($this->User->save($this->data)) 
     { 
     $this->Session->setFlash(__('The User has been saved', true)); 
     $this->redirect(array('action'=>'index')); 
     } 
     else 
     { 
     $this->Session->setFlash(__('The User could not be saved. Please, try again.', true)); 
     } 
    } 
    } 

    function edit($id = null) 
    { 
    if (!$id && empty($this->data)) 
    { 
     $this->Session->setFlash(__('Invalid User', true)); 
     $this->redirect(array('action'=>'index')); 
    } 
    if (!empty($this->data)) 
    { 
     if ($this->User->save($this->data)) 
     { 
     $this->Session->setFlash(__('The User has been saved', true)); 
     $this->redirect(array('action'=>'index')); 
     } 
     else 
     { 
      $this->Session->setFlash(__('The User could not be saved. Please, try again.', true)); 
     } 
    } 
    if (empty($this->data)) 
    { 
     $this->data = $this->User->read(null, $id); 
    } 
    } 

    function delete($id = null) 
    { 
    if (!$id) 
    { 
     $this->Session->setFlash(__('Invalid id for User', true)); 
     $this->redirect(array('action'=>'index')); 
    } 
    if ($this->User->del($id)) 
    { 
     $this->Session->setFlash(__('User deleted', true)); 
     $this->redirect(array('action'=>'index')); 
    } 
    } 
} 

下面是測試:

/* SVN FILE: $Id$ */ 
/* UsersController Test cases generated on: 2009-08-05 17:08:03 : 1249507923*/ 
App::import('Controller', 'Users'); 

class TestUsers extends UsersController 
{ 
    var $autoRender = false; 
    var $redirectUrl; 
    var $redirectStatus; 
    var $renderedAction; 
    var $renderedLayout; 
    var $renderedFile; 
    var $stopped; 

    function redirect($url, $status = null, $exit = true) 
    { 
    $this->redirectUrl = $url; 
    $this->redirectStatus = $status; 
    } 

    function render($action = null, $layout = null, $file = null) 
    { 
    $this->renderedAction = $action; 
    $this->renderedLayout = (is_null($layout) ? $this->layout : $layout); 
    $this->renderedFile = $file; 
    } 

    function _stop($status = 0) 
    { 
    $this->stopped = $status; 
    } 
} 

class UsersControllerTest extends CakeTestCase 
{ 
    var $fixtures = array('user'); 
    var $Users = null; 

    function startTest() 
    { 
    $this->Users = new TestUsers(); 
    $this->Users->constructClasses(); 
    $this->Users->Component->initialize($this->Users); 
    } 

    function prepareForAction() 
    { 
    $this->Users->beforeFilter(); 
    $this->Users->Component->startup($this->Users); 
    } 

    function endTest() 
    { 
    $this->Users->Session->destroy(); 
    unset($this->Users); 
    ClassRegistry::flush(); 
    } 

    //----------------------------------------------------------------------- 

    function testUsersControllerInstance() 
    { 
    $this->assertTrue(is_a($this->Users, 'UsersController')); 
    } 

    function testLogin() 
    { 
    $this->Users->data = array(
     'User' => array(
     'username' => 'admin', 
     'password' => 'admin' 
    ) 
    ); 

    $this->prepareForAction(); 
    $this->Users->login(); 

    $this->assertNotNull($this->Users->redirectUrl); 
    $this->assertEqual($this->Users->Session->read('Auth.User.id'), 1); 
    } 
} 

回答

4

測試你有沒有真的測試你的UsersContoller,你真的在​​測試Au thComponent。如果你想做到這一點,你需要確保你的TestUsersController的設置與你的應用中的相同。在你TESTLOGIN的情況下,你需要設置控制器的動作和網址:

function testLogin() 
{ 
$this->Users->data = array(
       'User' => array(
        'username' => 'admin', 
        'password' => 'admin' 
       ) 
      ); 

$this->Users->params['url']['url'] = '/users/login'; 
$this->Users->params['action'] = 'login'; 
$this->prepareForAction(); 
$this->Users->login(); 

$this->assertNotNull($this->Users->redirectUrl); 
$this->assertEqual($this->Users->Session->read('Auth.User.id'), 1); 
} 

或者,我建議我們再看一下Mark's mock objects post,並利用這些方法來寫的控制器代碼測試和嘲諷AUTH組件。