我正在尝试测试一个仅应该从这样的元素调用的控制器动作:
$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对象。
答案 0 :(得分: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'
)
));
}
答案 1 :(得分:0)
无法修改CakeRequest
正在使用的模拟ControllerTestCase::_testAction
对象。
你唯一的机会是继承ControllerTestCase
,在那里复制_testAction
方法,并在传递params或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']};
}
}