单元测试Auth组件

时间:2013-08-14 07:08:51

标签: cakephp authentication testing

我使用以下代码测试UsersController中的登录操作

public function testLogin() {
    $data = array('User' => array(
                'username' => 'hello',
                'password' => '411'
                    )
            );
    $this->Users = $this->generate('Users',array('components'=> array('Auth','Session')));
    $this->Users->Auth->staticExpects($this->once())
                        ->method('user')
                        ->with('id');
    $this->testAction('/users/login', array('data' => $data, 'method' => 'post'));

}

,夹具是 -

class UserFixture extends CakeTestFixture {
    public $import = array('model' => 'User', 'records' => true, 'connection' => 'fixture');
}

adn action is -

public function login() {

        if($this->request->is('post')) {
            if($this->Auth->login()) {
                $this->redirect($this->Auth->redirect());
            } else {
                return false;
                $this->Session->setFlash(__('Wrong Username Or Password,Please Try Again'));
            }
        }
    }

始终显示

  

方法名称的期望失败等于1次调用时。   预计方法被调用1次,实际上被称为0次。

有什么问题?找不到任何解决方案,原因也是。请帮助。

2 个答案:

答案 0 :(得分:2)

我认为模拟auth组件的问题是除了在组件数组中包含auth之外,还需要指定要模拟的Auth的哪些方法,以及如何模拟它们。

我在测试中处理AuthComponent的方法是使用方法创建一个超类:_generateMockWithAuthUserId,它可以模拟Auth组件,以及我需要的方式。

我从下面的超类中粘贴了代码。

class AppControllerTest extends ControllerTestCase {

    public function setUp() {
        parent::setUp();
        $this->User = ClassRegistry::init('User');
    }

    public function tearDown() {
        unset($this->User);
        parent::tearDown();
    }

    public function testPlaceholder(){
        // This just here so we don't get "Failed - no tests found in class AppControllerTest"
        $this->assertTrue(true);
    }

    protected function _generateMockWithAuthUserId($contollerName, $UserId){
        $this->authUserId = $UserId;
        $this->authUser = $this->User->findById($this->authUserId);
        $this->controller = $this->generate($contollerName, array(
            'methods' => array(
                '_tryRememberMeLogin',
                '_checkSignUpProgress'
            ),
            'components' => array(
                'Auth' => array(
                    'user',
                    'loggedIn',
                ),
                'Security' => array(
                    '_validateCsrf',
                ),
                'Session',
            )
        ));

        $this->controller->Auth
            ->expects($this->any())
            ->method('loggedIn')
            ->will($this->returnValue(true));

        $this->controller->Auth
            ->staticExpects($this->any())
            ->method('user')
            ->will($this->returnCallback(array($this, 'authUserCallback')));

    }

    public function authUserCallback($param){
        if(empty($param)){
            return $this->authUser['User'];
        } else {
            return $this->authUser['User'][$param];
        }
    }
}

然后这是一个继承自该超类的类的示例。记下它在何处/如何调用_generateMockWithAuthUserId。基本上,这样做会设置一个合适的控制器,并使用Auth模拟相应的用户ID。

<?php
require_once dirname(__FILE__) . DS . 'AppControllerTest.php';

class EmployeeNotesControllerTestCase extends AppControllerTest {

    public $fixtures = array(
        // your fixtures go here
    );

    public function setUp() {
        parent::setUp();
        $this->EmployeeNote = ClassRegistry::init('EmployeeNote');
    }

    public function tearDown() {
        unset($this->EmployeeNote);
        parent::tearDown();
    }

    public function testSupervisorIndexCanNotSeeNotesOnSelf() {
        $authUserId = 1;
        $this->_generateMockWithAuthUserId('EmployeeNotes', $authUserId);

        $this->controller->Session
                ->expects($this->once())
                ->method('setFlash');

        $result = $this->testAction('supervisor/employee_notes/index/'.$authUserId, array('return' => 'vars', 'method' => 'get'));

        $this->assertTrue(empty($result['employeeNotes']));
    }
}

希望有所帮助。

答案 1 :(得分:0)

我找到了解决方案。工作正常。

public function testLogin() {
    $data = array('User' => array(
            'username' => 'sasa',
            'password' => '111'
            )
        );
    $this->Users = $this->generate('Users', array());
    $result = $this->testAction('/users/login', array('data' => $data, 'method' => 'post'));

    $this->assertEquals($data['User']['username'],$this->Users->Session->read('Auth.User.username'));
    $result = $this->testAction('/users/logout');
}