-1

我正在为我的一个控制器编写 CakePHP 单元测试。控制器对该方法进行了多次调用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()调用(没有参数的调用)并且失败并出现错误:

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

如何为 AuthComponent 获得适当的模拟,以便获得所有字段/变量?

4

1 回答 1

2

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

我有一个 AppControllerTest.php 超类,它为“用户”方法返回一个回调。回调处理有和没有参数的情况。这_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。

于 2013-10-18T19:06:59.510 回答