Search code examples
phpspec

Why does PHPSpec fail to test thrown exceptions using ::shouldThrow()?


I am trying to test whether a method throws an exception in PHPSpec. Here is the method being tested; it is either running a Callable or a controller's action. I am trying to test whether the exception at the end is being thrown.

function dispatch($target, $params=array()) 
{
    // call closure?
    if( is_callable( $target ) ) {
        call_user_func_array( $target, $params ); 
        return true;
    }   

    // call controller
    list($controllerClass, $actionMethod) = explode('@', $target);
    $controllerClass = $this->controllerNamespace . '\\' . $controllerClass;
    if (!class_exists($controllerClass)) {
        throw new \Exception('Controller not found: '.$controllerClass);
    }
}

Here is the PHPSpec test case:

function it_throws_an_exception_if_the_controller_class_isnt_callable()
{
   $this->shouldThrow('\Exception')->duringDispatch('Nonexistentclass@Nonexistentmethod', array());
}

This is consistent with the documentation on PHPSpec: http://www.phpspec.net/en/latest/cookbook/matchers.html#throw-matcher

The problem is if I comment the throw new \Exception line, this test still passes. It doesn't appear to test the method at all. What am I doing wrong?


Solution

  • Create a new exception class, throw it in dispatch() instead of \Exception and check in phpspec if that exception is thrown.

    From the behaviour you described I suspect dispatch() throws an \Exception before reaching the if (! class_exists()) statement (even that line could be the culprit if the autoloader throws an exception).

    I pasted your function into a class of my project (it happened I was working with phpspec right now) and the spec worked flawless in both cases (when the exception is thrown and when the throw \Exception line was commented out).