CakePHP 控制器的实际测试?

发布于 2024-07-30 18:31:27 字数 5464 浏览 2 评论 0原文

我正在使用 SimpleTest 1.0.1 使用 CakePHP(刚刚发布的 1.2.4)编写一个新应用程序。 我已阅读Cookbook的相关部分,在Bakery,并阅读 Mark Story 关于控制器测试的帖子(困难方式使用模拟)。

不幸的是,这些都没有讨论非平凡控制器的实际测试。 许多应用程序将网站的某些区域置于登录后面,但我无法弄清楚如何测试以下简单场景:

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

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

FAILED [NULL] 在 [.../app/tests/cases/controllers/users_controller.test.php 第 79 行] 不应为空 .../app/tests/cases/controllers/users_controller.test.php -> 用户控制器测试 -> 测试登录

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

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

这是控制器(加上 Mark Story 的“hard way”测试方法):

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);
  }
}

I'm writing a new application with CakePHP (just-released 1.2.4), using SimpleTest 1.0.1. I have read the relevant sections of the Cookbook, searched on the Bakery, and read Mark Story's postings on controller testing (the hard way and with mocks).

Unfortunately, none of this talks about real-world testing of non-trivial controllers. Lots of apps put areas of the site behind a login, yet I cannot figure out how to test the simple scenario of:

  • guest access to protected page redirects?
  • valid credentials sets expected session variables?
  • invalid credentials re-displays login page with error message?

The controller and test below do not work as I thought they would. Both assertions fail and I also get a PHP error:

FAILED
[NULL] should not be null at [.../app/tests/cases/controllers/users_controller.test.php line 79]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin

FAILED
Equal expectation fails as [NULL] does not match [Integer: 1] at [.../app/tests/cases/controllers/users_controller.test.php line 80]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin

ERROR
Unexpected PHP error [Undefined index: action] severity [E_NOTICE] in [.../cake/libs/controller/components/auth.php line 266]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin

Here is the controller (baked plus Mark Story's "hard way" testing method):

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'));
    }
  }
}

Here is the test:

/* 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);
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

输什么也不输骨气 2024-08-06 18:31:27

您进行的测试并不是真正测试您的 UsersContoller,而是真正测试 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);
}

或者,我建议再看一下 标记模拟对象发布 并使用这些方法为控制器代码编写测试并模拟身份验证组件。

The test you have isn't really testing your UsersContoller, you're really testing the AuthComponent. If you want to do this you need to make sure you setup your TestUsersController the same as it would be in your app. In the case of your testLogin you need to set the controller's action and 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);
}

Alternately, I would suggest taking another look at Mark's mock objects post and using those methods to write tests for the controller code and mocking the auth component.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文