如何使用PHPUnit测试确切的Exception消息而不是子字符串?

Bry*_*son 6 php phpunit unit-testing exception-handling php-5.3

按照PHPUnit文档@expectedExceptionMessage,字符串只能是实际的子Exception抛出。

在我的一种验证方法中,为发生的每个错误推送一个数组项,并Exception通过内嵌错误数组来显示最终消息。

class MyClass
{
    public function validate($a, $b, $c, $d)
    {
        if($a < $b) $errors[] = "a < b.";
        if($b < $c) $errors[] = "b < c.";
        if($c < $d) $errors[] = "c < d.";

        if(count($errors) > 0) throw new \Exception(trim(implode(" ", $errors)));
    }
}
Run Code Online (Sandbox Code Playgroud)

我这里的问题是,在PHPUnit测试方法中,我检查了不同的组合。这导致测试通过,我打算失​​败。

/**
 * @expectedException \Exception
 * @expectedExceptionMessage a < b.
 */
public function testValues_ALessBOnly()
{
    $myClass = new MyClass()
    $myClass->validate(1, 2, 4, 3);
}
Run Code Online (Sandbox Code Playgroud)

Exception消息的字符串实际上是,"a < b. b < c."但是此测试仍然通过。我打算使该测试失败,因为该消息与我期望的不完全相同。

PHPUnit有没有办法期望确切的字符串而不是子字符串?我希望避免以下情况:

public function testValues_ALessBOnly()
{
    $myClass = new MyClass()
    $fail = FALSE;

    try
    {
        $myClass->validate(1, 2, 4, 3);
    }
    catch(\Exception $e)
    {
        $fail = TRUE;
        $this->assertEquals($e->getMessage(), "a < b.";
    }

    if(!$fail) $this->fail("No Exceptions were thrown.");
}
Run Code Online (Sandbox Code Playgroud)

Vol*_* I. 6

你可以$this->expectExceptionMessage()用来处理这个。

例子:

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Some error message');
Run Code Online (Sandbox Code Playgroud)

  • 这仍然会导致“包含”检查(strpos)而不是等于/身份(===)检查。 (4认同)

cam*_*aca 5

发布此问题时,PHPUnit v3.7尚未解决此问题。较新的版本具有一个新@expectedExceptionMessageRegExp选项,可用于添加正则表达式以匹配异常消息。

您的情况下,使用^$强制字符串完全符合预期,如下所示:

/**
 * @expectedException \Exception
 * @expectedExceptionMessageRegExp /^a < b\.$/
 */
public function testValues_ALessBOnly()
{
    $myClass = new MyClass()
    $myClass->validate(1, 2, 4, 3);
}
Run Code Online (Sandbox Code Playgroud)


Far*_*mov 3

我尝试了很多方法来测试异常,最后我发现测试异常的最好方法是 try-catch 块。我建议您使用异常代码抛出异常,然后测试使用此代码是否抛出异常。例如,假设您的异常代码是 101

if(count($errors) > 0) throw new \Exception(trim(implode(" ", $errors)), 101);
Run Code Online (Sandbox Code Playgroud)

例如,假设您的异常代码是 101

try {
    $myClass->validate(1, 2, 4, 3);
    $this->fail( "Exception with 101 code should be thrown" );
} catch (Exception $e) {
    $this->assertEquals( 101, $e->getCode());
}
Run Code Online (Sandbox Code Playgroud)