【问题标题】:Mocking an authed user in CakePHP在 CakePHP 中模拟经过身份验证的用户
【发布时间】:2013-10-27 15:27:42
【问题描述】:

我正在为我的一个控制器编写 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) 与预期值不匹配。失败的 断言 null 匹配预期的“id”。

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

【问题讨论】:

    标签: php unit-testing cakephp phpunit


    【解决方案1】:

    这就是我的做法。请注意,在这段代码中,我使用 '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。

    【讨论】:

    • 谢谢,这让我克服了烦人的错误,并且是一个很好的结构,可以快速模拟所有测试中的 Auth。我最终在控制器开始工作之前用 $this-&gt;Auth-&gt;user 调用替换了我的静态 AuthComponent::user 调用(由于某种原因,静态方法一直返回 null)。
    猜你喜欢
    • 1970-01-01
    • 2020-11-15
    • 2016-01-17
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多