Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CakePHP控制器测试:模拟Auth组件 形势_Cakephp_Testing - Fatal编程技术网

CakePHP控制器测试:模拟Auth组件 形势

CakePHP控制器测试:模拟Auth组件 形势,cakephp,testing,Cakephp,Testing,控制器代码 <?php App::uses('AppController', 'Controller'); class PostsController extends AppController { public function isAuthorized() { return true; } public function edit($id = null) { $this->autoRender = false;

控制器代码

<?php
App::uses('AppController', 'Controller');

class PostsController extends AppController {

    public function isAuthorized() {
        return true;
    }

    public function edit($id = null) {
        $this->autoRender = false;

        if (!$this->Post->exists($id)) {
            throw new NotFoundException(__('Invalid post'));
        }

        if ($this->Post->find('first', array(
            'conditions' => array(
                'Post.id' => $id,
                'Post.user_id' => $this->Auth->user('id')
            )
        ))) {
            echo 'Username: ' . $this->Auth->user('username') . '<br>';
            echo 'Created: ' . $this->Auth->user('created') . '<br>';
            echo 'Modified: ' . $this->Auth->user('modified') . '<br>';
            echo 'All:';
            pr($this->Auth->user());
            echo 'Modified: ' . $this->Auth->user('modified') . '<br>';
        } else {
            echo 'Unauthorized.';
        }
    }
}
<?php
App::uses('PostsController', 'Controller');

class PostsControllerTest extends ControllerTestCase {

    public $fixtures = array(
        'app.post',
        'app.user'
    );

    public function testEdit() {
        $this->Controller = $this->generate('Posts', array(
            'components' => array(
                'Auth' => array('user')
            )
        ));

        $this->Controller->Auth->staticExpects($this->at(0))->method('user')->with('id')->will($this->returnValue(1));
        $this->Controller->Auth->staticExpects($this->at(1))->method('user')->with('username')->will($this->returnValue('admin'));
        $this->Controller->Auth->staticExpects($this->at(2))->method('user')->with('created')->will($this->returnValue('2013-05-08 00:00:00'));
        $this->Controller->Auth->staticExpects($this->at(3))->method('user')->with('modified')->will($this->returnValue('2013-05-08 00:00:00'));
        $this->Controller->Auth->staticExpects($this->at(4))->method('user')->will($this->returnValue(array(
            'id' => 1,
            'username' => 'admin',
            'created' => '2013-05-08 00:00:00',
            'modified' => '2013-05-08 00:00:00'
        )));

        $this->testAction('/posts/edit/1', array('method' => 'get'));
    }
}
测试代码

<?php
App::uses('AppController', 'Controller');

class PostsController extends AppController {

    public function isAuthorized() {
        return true;
    }

    public function edit($id = null) {
        $this->autoRender = false;

        if (!$this->Post->exists($id)) {
            throw new NotFoundException(__('Invalid post'));
        }

        if ($this->Post->find('first', array(
            'conditions' => array(
                'Post.id' => $id,
                'Post.user_id' => $this->Auth->user('id')
            )
        ))) {
            echo 'Username: ' . $this->Auth->user('username') . '<br>';
            echo 'Created: ' . $this->Auth->user('created') . '<br>';
            echo 'Modified: ' . $this->Auth->user('modified') . '<br>';
            echo 'All:';
            pr($this->Auth->user());
            echo 'Modified: ' . $this->Auth->user('modified') . '<br>';
        } else {
            echo 'Unauthorized.';
        }
    }
}
<?php
App::uses('PostsController', 'Controller');

class PostsControllerTest extends ControllerTestCase {

    public $fixtures = array(
        'app.post',
        'app.user'
    );

    public function testEdit() {
        $this->Controller = $this->generate('Posts', array(
            'components' => array(
                'Auth' => array('user')
            )
        ));

        $this->Controller->Auth->staticExpects($this->at(0))->method('user')->with('id')->will($this->returnValue(1));
        $this->Controller->Auth->staticExpects($this->at(1))->method('user')->with('username')->will($this->returnValue('admin'));
        $this->Controller->Auth->staticExpects($this->at(2))->method('user')->with('created')->will($this->returnValue('2013-05-08 00:00:00'));
        $this->Controller->Auth->staticExpects($this->at(3))->method('user')->with('modified')->will($this->returnValue('2013-05-08 00:00:00'));
        $this->Controller->Auth->staticExpects($this->at(4))->method('user')->will($this->returnValue(array(
            'id' => 1,
            'username' => 'admin',
            'created' => '2013-05-08 00:00:00',
            'modified' => '2013-05-08 00:00:00'
        )));

        $this->testAction('/posts/edit/1', array('method' => 'get'));
    }
}
问题 这里实际上有三个问题:

  • 测试代码非常重复
  • 测试输出中的第二个“修改”行为空。信息技术 在浏览器的输出中应为“2013-05-08 00:00:00”
  • 如果我要修改控制器代码,添加一行,上面写着
    echo'Email:'$此->身份验证->用户('email')。'
    '
    (仅举个例子)在“Username”和“Created”的
    回显之间,测试将失败,并出现以下错误:
    在序列索引2调用时,方法名称的预期失败等于。这是有意义的,因为(1)
    处的
    $This->不再正确
  • 我的问题
    我怎样才能模拟Auth组件,使其(1)不重复,(2)使测试输出与浏览器相同的内容,(3)允许我在任何地方添加
    $this->Auth->user('foo')
    代码而不破坏测试?

    在回答这个问题之前,我必须承认我没有使用CakePHP框架的经验。但是,我在PHPUnit与Symfony框架的合作方面有相当多的经验,也遇到过类似的问题。针对您的观点:

  • 见我对第3点的答复

  • 原因是您需要一个额外的
    …->staticExpects($this->at(5))…
    语句来覆盖对Auth->user()的第6次调用。这些语句不定义使用指定值调用Auth->user()时要返回的值。它们定义,例如,对Auth对象的第二次调用必须是对参数为“username”的方法user(),在这种情况下,将返回“admin”。但是,如果您在下一点中遵循该方法,这应该不再是一个问题

  • 我假设您在这里试图实现的是独立于Auth组件测试控制器(因为坦率地说,测试控制器对用户对象进行一系列getter调用是没有意义的)。在这种情况下,模拟对象被设置为存根,以始终返回一组特定的结果,而不是期望使用特定参数()进行一系列特定的调用。这可以通过在代码中将“$This->at(x)”替换为“$This->any()”来实现。然而,虽然这将否定我在第2点中提到的添加额外行的需要,但您仍然需要重复。遵循先编写测试再编写代码的TDD方法,我建议如下:

    public function testEdit() {
        $this->Controller = $this->generate('Posts', array(
            'components' => array(
                'Auth' => array('user')
            )
        ));
            $this->Controller->Auth
                ->staticExpects($this->any())
                ->method('user')
                ->will($this->returnValue(array(
                    'id' => 1,
                    'username' => 'admin',
                    'created' => '2013-05-08 00:00:00',
                    'modified' => '2013-05-08 00:00:00',
                    'email' => 'me@me.com',
                )));
    
        $this->testAction('/posts/edit/1', array('method' => 'get'));
    }
    
  • 这将允许您的控制器被更新,以便在模拟对象已经返回用户属性的情况下,按照任意顺序进行调用。可以编写模拟对象以返回所有用户属性(或者可能与此控制器相关的所有属性),而不管控制器是否检索这些属性以及检索它们的频率。(请注意,在您的特定示例中,如果您的模拟包含“email”,控制器中的pr()语句将从测试中输出与浏览器不同的结果,但我认为您不希望在不更新测试的情况下向记录添加新属性)

    以这种方式编写测试意味着您的控制器编辑功能需要类似于以下内容-更易于测试的版本:

    $this->autoRender = false;
    
    if (!$this->Post->exists($id)) {
        throw new NotFoundException(__('Invalid post'));
    }
    
    $user = $this->Auth->user();
    
    if ($this->Post->find('first', array(
        'conditions' => array(
            'Post.id' => $id,
            'Post.user_id' => Hash::get($user, 'id')
        )
    ))) {
        echo 'Username: ' . Hash::get($user, 'username') . '<br>';
        echo 'Created: ' . Hash::get($user, 'created') . '<br>';
        echo 'Modified: ' . Hash::get($user, 'modified') . '<br>';
        echo 'All:';
        pr($user);
        echo 'Modified: ' . Hash::get($user, 'modified') . '<br>';
    } else {
        echo 'Unauthorized.';
    }
    
    $this->autoRender=false;
    如果(!$this->Post->exists($id)){
    抛出新的NotFoundException(uuu('Invalid post'));
    }
    $user=$this->Auth->user();
    如果($this->Post->find('first',数组(
    “条件”=>数组(
    'Post.id'=>$id,
    'Post.user_id'=>Hash::get($user,'id'))
    )
    ))) {
    echo“Username:”.Hash::get($user,“Username”)。
    ; echo“Created:”.Hash::get($user,“Created”)。
    ; echo'Modified:'.Hash::get($user'Modified')。
    ; 呼应“全部:”; 公共关系(用户); echo'Modified:'.Hash::get($user'Modified')。
    ; }否则{ 回声“未经授权”; }
    据我所知,Hash::get($record,$key)是从记录中检索属性的正确CakePHP方法,尽管使用这里提供的简单属性,我认为用户[$key]也可以工作