TheWebs TheWebs - 3 months ago 6
PHP Question

How to reach the exception block

So I am messing around with symfony router component and I created a small wrapper.

One thing that came up was how do I get a request to throw a 500 in unit tests? The method in question is:

public function processRoutes(Request $request) {

try {
$request->attributes->add($this->_matcher->match($request->getPathInfo()));
return call_user_func_array($request->attributes->get('callback'), array($request));
} catch (ResourceNotFoundException $e) {
return new RedirectResponse('/404', 302);
} catch (Exception $e) {
return new RedirectResponse('/500', 302);
}
}


And the test in question is:

public function testFiveHundred() {
$router = new Router();

$router->get('/foo/{bar}', 'foo', function($request){
return 'hello ' . $request->attributes->get('bar');
});

$response = $router->processRoutes(Request::create('/foo/bar', 'GET'));

$this->assertEquals(500, $response->getStatusCode());
}


Right now the test will fail because we are defined and the status code will be 200. Is there something special I can do to the Request object I create, to make it throw a 500?

Answer

I think you got several options here you can play with:

  1. Decide that a specific path will always throw an exception.
    This will force you to make some changes in your code.


public function processRoutes(Request $request) {
    ...
        if ($request->getRequestUri() == '/path/that/throws/exception') {
            throw  Exception('Forced to throw exception by URL');
        }
    ...
}

public function testFiveHundred() {
    ...
    $response = $router->processRoutes(Request::create('/path/that/throws/exception', 'GET'));
    ...
}
  1. Make a DummyRequest object that will extends your original Request class and make sure this object will raise an Exception (for example - you know for sure that you use the getPathInfo(), so you can use this).


class DummyRequest extends Request {

    public function getPathInfo() {
        throw new Exception('This dummy request object should only throw an exception so we can test our routes for problems');
    }

}

public function testFiveHundred() {
    ...
    $dummyRequest = new DummyRequest();
    $response = $router->processRoutes($dummyRequest);
    ...
}

Since the function getRequestUri of our $dummyRequest throws an exception, your call to $router->processRoutes will have our dummy to throw that exception.

This is a general idea, you would probably need to play a bit with the namespaces and the functions there (I didn't test it, however this should work).

Comments