2009-08-07 59 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组件。