在CakePHP中模拟一个authed用户

时间:2013-10-18 17:22:56

标签: php unit-testing cakephp phpunit

我正在为我的一个控制器编写CakePHP单元测试。 Controller对AuthComponent::user()方法进行了多次调用,以读取当前登录用户的数据。有3种用法:

  • AuthComponent::user()(没有参数,取整个数组)
  • AuthComponent::user('id')(获取用户ID)
  • AuthComponent::user('name')(提取用户名)

我在测试中尝试了两种模拟AuthComponent的方法:

// Mock the Controller and the Components
$this->controller = $this->generate('Accounts', array(
    'components' => array(
        'Session', 'Auth' => array('user'), 'Acl'
    )
));

// Method 1, write the entire user array
$this->controller->Auth->staticExpects($this->any())->method('user')
    ->will($this->returnValue(array(
        'id' => 2,
        'username' => 'admin',
        'group_id' => 1
    )));

// Method 2, specifically mock the AuthComponent::user('id') method
$this->controller->Auth->staticExpects($this->any())->method('user')
    ->with('id')
    ->will($this->returnValue(2));

但这些方法对我不起作用。方法1似乎根本不做任何事情,我的控制器中使用当前登录用户的id的保存操作返回null,因此未正确设置/获取该值。

方法2似乎有效,但是过于宽泛,它也会尝试将自己绑定到AuthComponent::user()调用(没有params的调用),并且失败并显示错误:

  

方法名称的期望失败等于何时   调用零次或多次参数0进行调用   AuthComponent :: user(null)与期望值不匹配。失败   断言null匹配预期的'id'。

如何为AuthComponent获取正确的模拟,以便可以获得所有字段/变量?

1 个答案:

答案 0 :(得分:2)

我就是这样做的。请注意,在此代码中,我使用“Employee”作为我的用户模型,但它应该很容易更改。

我有一个AppControllerTest.php超类,它返回'user'方法的回调。回调处理带有和没有参数的情况。 _generateMockWithAuthUserId就是您所追求的 - 但请全部阅读。还有一些值得注意的事情,比如testPlaceholder。这是我的全班:

<?php
App::uses('Employee', 'Model');

/**
 * EmployeeNotesController Test Case
 * Holds common Fixture ID's and mocks for controllers
 */
class AppControllerTest extends ControllerTestCase {

    public $authUserId;

    public $authUser;

/**
 * setUp method
 *
 * @return void
 */
    public function setUp() {
        parent::setUp();
        $this->Employee = ClassRegistry::init('Employee');
    }

/**
 * tearDown method
 *
 * @return void
 */
    public function tearDown() {
        unset($this->Employee);
        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, $employeeId) {
        $this->authUserId = $employeeId;
        $this->authUser = $this->Employee->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['Employee'];
        } else {
            return $this->authUser['Employee'][$param];
        }
    }
}

然后,我的控制器测试用例继承自该类:

require_once dirname(__FILE__) . DS . 'AppControllerTest.php';
class EmployeeNotesControllerTestCase extends AppControllerTest {
    // Tests go here

当你想在测试中模拟auth组件时,你可以调用

$this->_generateMockWithAuthUserId('EmployeeNotes', $authUserId);

其中'EmployeeNotes'是控制器的名称,$ authUserId是测试数据库中用户的ID。