为什么 PHPSpec 无法使用 ::shouldThrow() 测试抛出的异常?

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

我正在尝试测试一个方法是否在 PHPSpec 中抛出异常。这是正在测试的方法;它是 运行 Callable 或控制器的操作。我正在尝试测试最后是否抛出异常。

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);
    }
}

这是 PHPSpec 测试用例:

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

这与 PHPSpec 上的文档一致: http://www.phpspec.net/en/latest/cookbook/matchers.html#throw-matcher

问题是如果我注释掉 throw new \Exception 行,这个测试仍然通过。它似乎根本没有测试该方法。我做错了什么?

创建一个新异常 class,将其抛入 dispatch() 而不是 \Exception 并在 phpspec 中检查是否抛出该异常。

根据你描述的行为,我怀疑 dispatch() 在到达 if (! class_exists()) 语句之前抛出一个 \Exception(如果自动加载器抛出异常,即使那一行也可能是罪魁祸首)。

我将你的函数粘贴到我项目的 class 中(碰巧我现在正在使用 phpspec)并且规范在两种情况下都完美无缺(当抛出异常时以及当throw \Exception 行被注释掉了)。