代码之家  ›  专栏  ›  技术社区  ›  Steve Madsen

CakePHP控制器的真实测试?

  •  5
  • Steve Madsen  · 技术社区  · 15 年前

    我正在用CakePHP(刚刚发布的1.2.4)编写一个新的应用程序,使用SimpleTest 1.0.1。我已经阅读了 Cookbook ,搜索 Bakery ,并阅读Mark Story在控制器测试(the hard way with mocks ).

    不幸的是,这些都没有提到对非平凡控制器的实际测试。许多应用程序将站点的各个区域放在登录之后,但我无法确定如何测试以下简单场景:

    • 来宾访问受保护的页面重定向?
    • 有效凭据设置预期的会话变量?
    • 无效凭据是否重新显示带有错误消息的登录页?

    下面的控制器和测试并不像我想象的那样工作。两个断言都失败了,我还得到一个PHP错误:

    失败 [空]不应为空,位于[…/app/tests/cases/controllers/users_controller.test.php第79行] …/app/tests/cases/controllers/users_controller.test.php->用户控制器测试->测试登录

    失败 相等期望失败,因为[NULL]与[Integer:1]不匹配,位于[…/app/tests/cases/controllers/users_controller.test.php第80行] …/app/tests/cases/controllers/users_controller.test.php->用户控制器测试->测试登录

    错误 […/cake/libs/controller/components/auth.PHP第266行中出现意外的PHP错误[未定义的索引:操作]严重性[E_NOTICE] …/app/tests/cases/controllers/users_controller.test.php->用户控制器测试->测试登录

    以下是控制器(baked plus Mark Story的“硬方法”测试方法):

    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);
      }
    }
    
    1 回复  |  直到 11 年前
        1
  •  4
  •   alairock    12 年前

    您所做的测试并不是真正测试您的用户控制器,而是真正测试AuthComponent。如果你想这样做,你需要确保你设置的TestUsersController与你的应用程序中的相同。对于testLogin,您需要设置控制器的操作和url:

    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组件。