2

我正在尝试测试一个只应该从这样的元素调用的控制器操作:

$notes = $this->requestAction(array(
        'controller' => 'notes'
    ) , array(
        'pass' => array(
            'location' => $requestUrl
        )
    ));

在操作本身上,有一个检查以确保该操作是“请求的”:

public function index() {
    if (!empty($this->params['requested'])) {
        ...
        return $notes;
    } else {
        throw new ForbiddenException();
    }
}

如何测试上面的代码?以下:

$this->testAction('/notes', array(

                'passed' => array('location'=>'location1'),

                'return' => 'vars'

            ));

触发 ForbiddenException。我尝试使用 $this->generate 但我不确定我应该如何生成 $this->controller->params 对象。

4

2 回答 2

2

谢谢@nanoman 的回复。但是,我找到了一个更简单的解决方案(不知道我之前为什么想到这个)。写在这里以备将来参考。

只需从测试中调用 requestAction !

function testMytest() {
    $this->controller = $this->generate('Notes', array(
           'components' => array(
                'Auth'
            )
        ));
    $notes = $this->controller->requestAction(array(
        'controller' => 'notes'
    ) , array(
        'pass' => array(
            'location' => 'location1'
        )
    ));
}
于 2013-02-23T15:13:18.323 回答
0

无法修改正在使用的模拟CakeRequest对象ControllerTestCase::_testAction

您唯一的机会是子类ControllerTestCase化,复制其中的_testAction方法,并向您传递参数或CakeRequest要使用的对象的方法添加一个附加参数。请参阅下面的实现。

在您的测试用例中,您将按如下方式使用它:

$testUrl = '/notes';
$request = $this->getMock('CakeRequest', array('_readInput'), array($testUrl));
$request->addParams(array('requested' => true));
$this->testAction('/notes', array(
    'passed' => array('location'=>'location1'),
    'return' => 'vars',
    'request' => $request
));

MyControllerTestCase

class MyControllerTestCase() {
    protected function _testAction($url = '', $options = array()) {
        $this->vars = $this->result = $this->view = $this->contents = $this->headers = null;

        $options = array_merge(array(
            'data' => array(),
            'method' => 'POST',
            'return' => 'result',
            'request' => null
        ), $options);

        $restore = array('get' => $_GET, 'post' => $_POST);

        $_SERVER['REQUEST_METHOD'] = strtoupper($options['method']);
        if (is_array($options['data'])) {
            if (strtoupper($options['method']) == 'GET') {
                $_GET = $options['data'];
                $_POST = array();
            } else {
                $_POST = $options['data'];
                $_GET = array();
            }
        }

        if($options['request'] instanceof CakeRequest) {
            $request = $options['request'];
        } else {
            $request = $this->getMock('CakeRequest', array('_readInput'), array($url));
        }

        if (is_string($options['data'])) {
            $request->expects($this->any())
                ->method('_readInput')
                ->will($this->returnValue($options['data']));
        }

        $Dispatch = new ControllerTestDispatcher();
        foreach (Router::$routes as $route) {
            if ($route instanceof RedirectRoute) {
                $route->response = $this->getMock('CakeResponse', array('send'));
            }
        }
        $Dispatch->loadRoutes = $this->loadRoutes;
        $Dispatch->parseParams(new CakeEvent('ControllerTestCase', $Dispatch, array('request' => $request)));
        if (!isset($request->params['controller']) && Router::currentRoute()) {
            $this->headers = Router::currentRoute()->response->header();
            return;
        }
        if ($this->_dirtyController) {
            $this->controller = null;
        }

        $plugin = empty($request->params['plugin']) ? '' : Inflector::camelize($request->params['plugin']) . '.';
        if ($this->controller === null && $this->autoMock) {
            $this->generate($plugin . Inflector::camelize($request->params['controller']));
        }
        $params = array();
        if ($options['return'] == 'result') {
            $params['return'] = 1;
            $params['bare'] = 1;
            $params['requested'] = 1;
        }
        $Dispatch->testController = $this->controller;
        $Dispatch->response = $this->getMock('CakeResponse', array('send'));
        $this->result = $Dispatch->dispatch($request, $Dispatch->response, $params);
        $this->controller = $Dispatch->testController;
        $this->vars = $this->controller->viewVars;
        $this->contents = $this->controller->response->body();
        if (isset($this->controller->View)) {
            $this->view = $this->controller->View->fetch('__view_no_layout__');
        }
        $this->_dirtyController = true;
        $this->headers = $Dispatch->response->header();

        $_GET = $restore['get'];
        $_POST = $restore['post'];

        return $this->{$options['return']};
    }
}
于 2013-02-21T09:22:05.333 回答