如何模拟返回AuthComponent值的appModel方法

时间:2014-04-19 12:25:09

标签: php unit-testing cakephp phpunit cakephp-2.0

我正在测试一个控制器方法,该方法使用AppModel方法获取登录用户的帐户。问题是,我无法有效地模拟提供account_id的AppModel方法,而是在调试此值时获取null。请让我知道我错过了什么,或者我是否以错误的方式解决这个问题。

AppModel.php包括:

/**
 * _getUser
 *
 * @param string $key from AuthComponent::user
 * @return string value from AuthComponent::user
 */
    public function _getUser($key = null) {
        return AuthComponent::user($key);
    }

AccountsController.php包括:

App::uses('AppController', 'Controller');
class AccountsController extends AppController {

    public $name = 'Accounts';

/**
 * memberLetters -
 *  Generate a letter to each member
 *
 **/
    function memberLetters() {
        $account_id = $this->Account->_getUser('account_id');
        debug($account_id); // !!! returns null; expecting '1' !!!
    }
}

用户模型(User.php)包括:

App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
    public $name = 'User';
    public $actsAs = array('Acl' => array('type' => 'requester'));

    public $validate = array(
        'email' => array(
            'email' => array(
                'rule' => array('email'),
                'message' => 'Email address required'),
            'isUnique' => array(
                'rule' => array('isUnique'),
                'message' => 'This email address is already associated with an account.')
        ),
        'password' => array(
            'notempty' => array(
                'rule' => array('notempty'),
                'message' => 'Password required',
            ),
        ),
        'account_id' => array(
            'numeric' => array(
                'rule' => array('numeric'),
            ),
        ),
    );

    public $belongsTo = array('Account');
}

测试代码:AccountsControllerTest.php包括:

App::uses('AccountsController', 'Controller');
class AccountsControllerTest extends ControllerTestCase {

/**
 * Fixtures
 *
 * @var array
 */
    public $fixtures = array(
        'app.account',
        'app.user',
    );

/**
 * testMemberLetters method
 *
 * @return void
 */
    public function testMemberLetters() {
        $model = $this->getMockForModel('Account', array('_getUser'), array());

        $model
            ->expects($this->exactly(1))
            ->method('_getUser', array('account_id'))
            ->will($this->returnValue(1));

        $result = $this->testAction(
            'accounts/memberLetters',
            array(
                'method' => 'get',
                'return' => 'vars',
            )
        );


 }

1 个答案:

答案 0 :(得分:0)

我通过将Accounts :: get_User()调用从AccountsController代码重构到Account模型代码来解决这个问题。这使它成为可测试的。感谢TimKoschützkihttp://debuggable.com/posts/implementing-different-types-for-cakes-modelfind-method:485030de-4778-456e-8400-44d84834cda3我找到了以下方式来覆盖模型 - >找到:

Accounts.php包含

function find($type = string, $queryData = array()) {
    switch ($type) {
        case 'mine':
            if (!in_array('conditions', $queryData)) {
                $queryData['conditions'] =
                    array('id' => $this->_getUser('account_id'));
            } else {
                $queryData['conditions'] .=
                    array('id' => $this->_getUser('account_id'));
            }
            return parent::find('first', $queryData);
        default:
            return parent::find($type, $queryData);
    }
}

所以现在我的AccountsController方法可以简单地调用

$data = $this->Account->find('mine');

在我的AccountsControllerTest中我写了

public function testMemberLetters() {
    $this->controller = $this->generate('Accounts', array(
        'models' => array(
            'Account' => array('_getUser')
        )
    ));

    $this->controller->Account->expects($this->exactly(1))
        ->method('_getUser')
        ->with('account_id')
        ->will($this->returnValue(1));

    $result = $this->testAction(
        'accounts/memberLetters',
        array(
            'method' => 'get',
            'return' => 'vars',
        )
    );
}