PHPUnit 在预期异常后不会继续测试

2022-08-30 14:23:06

为什么 PHPUnit 不在此代码中执行最后一个异常断言?

public function testConfigOverriding()
{
    $this->dependencyContainer = new DependencyContainer(__DIR__ . "/../../Resources/valid_json.json");
    $this->assertEquals('overriden', $this->dependencyContainer->getConfig('shell_commander')['pygmentize_command']);

    $unexisting = "unexisting_file";
    $this->setExpectedException('Exception', "Configuration file at path \"$unexisting\" doesn't exist.");
    $this->dependencyContainer = new DependencyContainer($unexisting);

    $invalid = __DIR . "/../../Resources/invalid_json.json";
    $this->setExpectedException('Exception', "Configuration JSON file provided is not valid.");
    $this->dependencyContainer = new DependencyContainer($invalid);
}

所以基本上:它测试是否抛出了“unexsisting_file”异常,但完全忽略了“无效的json”测试。我是否需要对引发的每个异常进行单独的测试?


答案 1

即使使用 ,您的测试仍然是常规的 PHP 代码,并遵循 PHP 的正常规则。如果引发异常,程序流会立即跳出当前上下文,直到到达 / 块。setExpectedExceptiontrycatch

在 PHPUnit 中,当您使用 时,它会告诉 PHPUnit 的核心,当它应该期待即将运行的代码出现异常时。因此,它使用/ block等待它,如果以它期望的异常类型调用,则通过测试。setExpectedExceptiontrycatchcatch

但是,在您的测试方法中,正常的PHP规则仍然适用 - 当异常发生时,这是当前代码块的结束。该方法中的任何内容都不会被执行,除非您在测试方法中有自己的/块。trycatch

因此,为了测试多个异常,您有几个选择:

  1. 将您自己的/ 添加到测试方法中,以便您可以在第一次异常之后在该方法中继续进行进一步的测试。trycatch

  2. 将测试拆分为单独的方法,以便每个异常都位于其自己的测试中。

  3. 这个特殊的例子看起来是使用PHPUnit机制的一个很好的例子,因为你基本上是用两组数据测试相同的功能。该功能允许您定义一个单独的函数,该函数包含要测试的每组值的输入数据数组。然后将这些值一次传递一组到测试方法中。您的代码将如下所示:dataProviderdataProvider

    /**
     * @dataProvider providerConfigOverriding
     */
    public function testConfigOverriding($filename, $expectedExceptionText) {
        $this->dependencyContainer = new DependencyContainer(__DIR__ . "/../../Resources/valid_json.json");
        $this->assertEquals('overriden', $this->dependencyContainer->getConfig('shell_commander')['pygmentize_command']);
    
        $this->setExpectedException('Exception', $expectedExceptionText);
        $this->dependencyContainer = new DependencyContainer($filename);
    }
    
    public function providerConfigOverriding() {
        return array(
            array('unexisting_file', 'Configuration file at path "unexisting_file" doesn\'t exist.'),
            array(__DIR__ . "/../../Resources/invalid_json.json", "Configuration JSON file provided is not valid."),
        );
    }
    

希望有所帮助。


答案 2

我发现在异常发生后继续测试的最简单方法是在测试中实现try/final块。这实质上允许测试的执行继续进行,而不考虑引发任何异常。

这是我的实现:

$this->expectException(InvalidOperationException::class);

try {
    $report = $service->executeReport($reportId, $jobId);
} finally {
    $this->assertEquals($report->getStatus(), StatusMapper::STATUS_ABORTED);
}

推荐