如何测试使用 AuthComponent::user 内部的模型方法


how to test a Model method that uses AuthComponent::user inside

我正在使用CakePHP 2.4

我有一个名为Storybook的模型课程。

有一个名为createDraft的方法,其代码如下所示:

    public function createDraft($data) {
        $data['Storybook']['author']    = AuthComponent::user('id');

当我使用 CakePHP 测试编写测试脚本时,我在实例化 AuthComponent 中的用户数据时遇到了问题。

我的测试脚本如下所示:

<?php
App::uses('Storybook', 'Model');
class StorybookTestCase extends CakeTestCase {
/**
 * Fixtures
 *
 * @var array
 */
    public $fixtures = array(...
    );
/**
 * setUp method
 *
 * @return void
 */
    public function setUp() {
        parent::setUp();
        $this->Storybook    = ClassRegistry::init('Storybook');
...
...

/**
 * GIVEN we have only a title
 * WHEN we call createDraft
 * THEN we have a new draft
 *
 * @return void
 */
     public function testCreateDraftSuccessfully() {    
        // GIVEN only a title
        $data = array('Storybook' => array('title' => 'some title'));
        // WHEN we call the createDraft
        $actualResult = $this->Storybook->createDraft($data);
 ....

测试在创建草稿方法时失败。

我无法在 setUp 方法中使用用户数据填写身份验证组件,因为身份验证组件登录方法不是静态的。

请指教。

经过一些谷歌搜索并询问 IRC 频道后我想出的步骤 #cakephp:

1(确保您至少使用CakePHP 2.3

2( 在应用模型中创建以下受保护的函数:

protected function _getUser($key = null) {
    return AuthComponent::user($key);
}

3( 确保在 AppModel 中实际使用AuthComponent:

//type this just below App::uses('Model', 'Model');
App::uses('AuthComponent', 'Controller/Component');

4( 将故事书模型更改为使用 _getUser 而不是 AuthComponent::user

    public function createDraft($data) {
        $data['Storybook']['author']    = $this->_getUser('id');

5( 根据本文档,将以下内容添加到测试方法中:

public function testCreateDraftSuccessfully() {    
        // MOCK the _getUser method to always return 23 because we always expect that
        $this->Storybook = $this->getMockForModel('Storybook', array('_getUser'));
        $this->Storybook->expects($this->once())
        ->method('_getUser')
        ->will($this->returnValue(23));
    // GIVEN only a title
    $data = array('Storybook' => array('title' => 'some title'));

这将帮助您通过测试。

更新

如果您正在模拟的方法可能根据不同的参数返回不同的结果,则需要另一个公共函数作为模拟方法的回调。

步骤 5 的替代(如果您希望在参数为"id"时始终返回 23,如果参数为"group_id",则始终返回 1,请添加以下函数

public function getUserCallBack($field) {
        if ($field == 'id') {
            return 23;
        }
        if ($field == 'group_id') {
            return 1;
        }
    }

6( 将测试方法更改为:

public function testCreateDraftSuccessfully() {    
        // MOCK the _getUser method to always return 23 for _getUser('id') and 1 for _getUser('group_id')
        $this->Storybook = $this->getMockForModel('Storybook', array('_getUser'));
        $this->Storybook->expects($this->once())
        ->method('_getUser')
        ->with($this->logicalOr(
            $this->equalTo('id'),
            $this->equalTo('group_id')
        ))
        ->will($this->returnCallback(array($this, 'getUserCallBack')));
    // GIVEN only a title
    $data = array('Storybook' => array('title' => 'some title'));

有用的 PHPunit 匹配器列表。例如

$this->once()
$this->never()