Реальное тестирование контроллеров CakePHP? - PullRequest
5 голосов
/ 07 августа 2009

Я пишу новое приложение с CakePHP (только что выпущенный 1.2.4), используя SimpleTest 1.0.1. Я прочитал соответствующие разделы Кулинарной книги , провел поиск по Пекарня и прочитал сообщения Марка Стори о тестировании контроллера ( трудный путь и с издевается ).

К сожалению, ничего из этого не говорит о реальном тестировании нетривиальных контроллеров. Многие приложения помещают области сайта за логином, но я не могу понять, как проверить простой сценарий:

  • гостевой доступ к защищенным перенаправлениям страниц?
  • допустимые учетные данные устанавливают ожидаемые переменные сеанса?
  • неверные учетные данные повторно отображает страницу входа с сообщением об ошибке?

Контроллер и тесты ниже не работают так, как я думал. Оба утверждения терпят неудачу, и я также получаю ошибку PHP:

FAILED [NULL] не должно быть равно нулю в [... / app / tests / case / controllers / users_controller.test.php строка 79] ... / app / tests / case / controllers / users_controller.test.php -> UsersControllerTest -> testLogin

FAILED Равное ожидание не выполняется, поскольку [NULL] не совпадает с [Integer: 1] в строке [... / app / tests / case / controllers / users_controller.test.php 80] ... / app / tests / case / controllers / users_controller.test.php -> UsersControllerTest -> testLogin

ОШИБКА Неожиданная ошибка PHP [Неопределенный индекс: действие] серьезность [E_NOTICE] в строке [... / cake / libs / controller / components / auth.php 266] ... / app / tests / case / controllers / users_controller.test.php -> UsersControllerTest -> testLogin

Вот контроллер (запеченный плюс метод тестирования "Strong" Марка Стори):

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 Ответ

4 голосов
/ 11 августа 2009

Тест, который у вас есть, на самом деле не тестирует ваш 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);
}

С другой стороны, я бы предложил еще раз взглянуть на фиктивные объекты Марка после и использовать эти методы для написания тестов для кода контроллера и насмешки над компонентом auth.

...