Testes do mundo real dos controladores CakePHP?

Estou escrevendo um novo aplicativo com CakePHP (apenas lançado 1.2.4), usando o SimpleTest 1.0.1. Eu li as seções relevantes do Cookbook , pesquisado no Bakery e leio as postagens de Mark Story no teste do controlador (o caminho difícil e com zombarias ).

Infelizmente, nada disso fala sobre testes do mundo real de controladores não triviais. Muitos aplicativos colocam áreas do site por trás de um login, mas não consigo descobrir como testar o cenário simples de:

  • access de visitante aos redirecionamentos de páginas protegidos?
  • credenciais válidas define variables ​​de session esperadas?
  • Credenciais inválidas reaparecem a página de login com mensagem de erro?

O controlador e o teste abaixo não funcionam como eu pensei que sim. As duas afirmações falham e também recebo um erro PHP:

FAILED [NULL] não deve ser nulo no [… / app / tests / cases / controllers / users_controller.test.php linha 79] … / app / tests / cases / controllers / users_controller.test.php -> UsersControllerTest -> testLogin

FALHA A expectativa igual falha quando [NULL] não coincide com [Inteiro: 1] no [… / app / tests / cases / controllers / users_controller.test.php linha 80] … / app / tests / cases / controllers / users_controller.test.php -> UsersControllerTest -> testLogin

Erro erro inesperado do PHP [índice indefinido: ação] gravidade [E_NOTICE] no [… / cake / libs / controller / components / auth.php linha 266] … / app / tests / cases / controllers / users_controller.test. php -> UsersControllerTest -> testLogin

Aqui está o controlador (assado mais o método de teste “difícil” do 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')); } } } 

Aqui está o teste:

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

O teste que você possui não está realmente testando seu UsersContoller, você está realmente testando o AuthComponent. Se você quiser fazer isso, você precisa ter certeza de configurar seu TestUsersController do mesmo modo que seria no seu aplicativo. No caso do seu testLogin, você precisa definir a ação do controlador e 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); } 

Alternativamente, eu sugiro dar uma nova olhada na publicação de objects falsificados de Mark e usar esses methods para escrever testes para o código do controlador e zombar do componente de autenticação.