Make exception rendererer more resiliant

Exceptions in beforeRender() should render correct error pages.

Fixes #3235
This commit is contained in:
mark_story 2012-09-27 21:38:20 -04:00
parent 99edef0abc
commit 393849a9ba
2 changed files with 42 additions and 19 deletions

View file

@ -290,11 +290,11 @@ class ExceptionRenderer {
$this->controller->layoutPath = null; $this->controller->layoutPath = null;
$this->controller->subDir = null; $this->controller->subDir = null;
$this->controller->viewPath = 'Errors/'; $this->controller->viewPath = 'Errors/';
$this->controller->viewClass = 'View';
$this->controller->layout = 'error'; $this->controller->layout = 'error';
$this->controller->helpers = array('Form', 'Html', 'Session'); $this->controller->helpers = array('Form', 'Html', 'Session');
$this->controller->render($template); $view = new View($this->controller);
$this->controller->response->body($view->render($template, 'error'));
$this->controller->response->type('html'); $this->controller->response->type('html');
$this->controller->response->send(); $this->controller->response->send();
} }

View file

@ -670,25 +670,49 @@ class ExceptionRendererTest extends CakeTestCase {
$exception = new MissingHelperException(array('class' => 'Fail')); $exception = new MissingHelperException(array('class' => 'Fail'));
$ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller = $this->getMock('Controller'); $ExceptionRenderer->controller = $this->getMock('Controller', array('render'));
$ExceptionRenderer->controller->helpers = array('Fail', 'Boom'); $ExceptionRenderer->controller->helpers = array('Fail', 'Boom');
$ExceptionRenderer->controller->request = $this->getMock('CakeRequest'); $ExceptionRenderer->controller->request = $this->getMock('CakeRequest');
$ExceptionRenderer->controller->expects($this->at(2)) $ExceptionRenderer->controller->expects($this->at(0))
->method('render') ->method('render')
->with('missingHelper') ->with('missingHelper')
->will($this->throwException($exception)); ->will($this->throwException($exception));
$ExceptionRenderer->controller->expects($this->at(4)) $response = $this->getMock('CakeResponse');
->method('render') $response->expects($this->once())
->with('error500') ->method('body')
->will($this->returnValue(true)); ->with($this->stringContains('Helper class Fail'));
$ExceptionRenderer->controller->response = $this->getMock('CakeResponse'); $ExceptionRenderer->controller->response = $response;
$ExceptionRenderer->render(); $ExceptionRenderer->render();
sort($ExceptionRenderer->controller->helpers); sort($ExceptionRenderer->controller->helpers);
$this->assertEquals(array('Form', 'Html', 'Session'), $ExceptionRenderer->controller->helpers); $this->assertEquals(array('Form', 'Html', 'Session'), $ExceptionRenderer->controller->helpers);
} }
/**
* Test that exceptions in beforeRender() are handled by outputMessageSafe
*
* @return void
*/
public function testRenderExceptionInBeforeRender() {
$exception = new NotFoundException('Not there, sorry');
$ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller = $this->getMock('Controller', array('beforeRender'));
$ExceptionRenderer->controller->request = $this->getMock('CakeRequest');
$ExceptionRenderer->controller->expects($this->any())
->method('beforeRender')
->will($this->throwException($exception));
$response = $this->getMock('CakeResponse');
$response->expects($this->once())
->method('body')
->with($this->stringContains('Not there, sorry'));
$ExceptionRenderer->controller->response = $response;
$ExceptionRenderer->render();
}
/** /**
* Test that missing subDir/layoutPath don't cause other fatal errors. * Test that missing subDir/layoutPath don't cause other fatal errors.
* *
@ -698,32 +722,31 @@ class ExceptionRendererTest extends CakeTestCase {
$exception = new NotFoundException(); $exception = new NotFoundException();
$ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller = $this->getMock('Controller'); $ExceptionRenderer->controller = $this->getMock('Controller', array('render'));
$ExceptionRenderer->controller->helpers = array('Fail', 'Boom'); $ExceptionRenderer->controller->helpers = array('Fail', 'Boom');
$ExceptionRenderer->controller->layoutPath = 'json'; $ExceptionRenderer->controller->layoutPath = 'json';
$ExceptionRenderer->controller->subDir = 'json'; $ExceptionRenderer->controller->subDir = 'json';
$ExceptionRenderer->controller->viewClass = 'Json'; $ExceptionRenderer->controller->viewClass = 'Json';
$ExceptionRenderer->controller->request = $this->getMock('CakeRequest'); $ExceptionRenderer->controller->request = $this->getMock('CakeRequest');
$ExceptionRenderer->controller->expects($this->at(1)) $ExceptionRenderer->controller->expects($this->once())
->method('render') ->method('render')
->with('error400') ->with('error400')
->will($this->throwException($exception)); ->will($this->throwException($exception));
$ExceptionRenderer->controller->expects($this->at(3)) $response = $this->getMock('CakeResponse');
->method('render') $response->expects($this->once())
->with('error500') ->method('body')
->will($this->returnValue(true)); ->with($this->stringContains('Not Found'));
$response->expects($this->once())
$ExceptionRenderer->controller->response = $this->getMock('CakeResponse');
$ExceptionRenderer->controller->response->expects($this->once())
->method('type') ->method('type')
->with('html'); ->with('html');
$ExceptionRenderer->controller->response = $response;
$ExceptionRenderer->render(); $ExceptionRenderer->render();
$this->assertEquals('', $ExceptionRenderer->controller->layoutPath); $this->assertEquals('', $ExceptionRenderer->controller->layoutPath);
$this->assertEquals('', $ExceptionRenderer->controller->subDir); $this->assertEquals('', $ExceptionRenderer->controller->subDir);
$this->assertEquals('View', $ExceptionRenderer->controller->viewClass);
$this->assertEquals('Errors/', $ExceptionRenderer->controller->viewPath); $this->assertEquals('Errors/', $ExceptionRenderer->controller->viewPath);
} }