如何使用数据提供程序在PHPUnit中测试异常?

10

PHPUnit有一个非常有用的功能@dataProvider,它允许测试一个方法的多个情况。 它还有另一个很棒的注释--@expectedException,以确保应用在指定位置抛出正确的Exception

我目前正在针对多个边缘情况测试一个方法,并希望将这两个特性组合起来使用(非工作代码):

class TestMyClass
{
    /**
     * @dataProvider provideDataForFoo
     */
    public function testFoo($paramBar, $paramBuz, $expected)
    {
        $myObject = new MyClass();
        $this->assertEquals($expected, $myObject->foo($paramBar, $paramBuz));
    }
    public function provideDataForFoo()
    {
        return [
            ['expected lorem', 'bar lorem', 'buz lorem'],
            ['expected ipsum', 'bar ipsum', 'buz ipsum'],
            ['expected exception', 'bar invalid argument', 'buz invalid argument'],
        ];
    }
}

如何在使用@dataProvider时将@expectedException用作其中一种情况?


2
如果只有一个集合应该抛出异常,您应该为此添加单独的测试。该测试应该调用实际引发异常的代码,因为assertEquals()不会这样做。 - jeroen
2个回答

8

PHPUnit不提供这种组合。但是可以通过一个简单的技巧来实现:

  1. 基本解决方案

为正常测试和异常测试分别编写测试方法。

class TestMyClass
{
    /**
     * @dataProvider provideDataForFoo
     */
    public function testFoo($paramBar, $paramBuz, $expected)
    {
        $myObject = new MyClass();
        $this->assertEquals($expected, $myObject->foo($paramBar, $paramBuz));
    }
    public function provideDataForFoo()
    {
        return [
            ['expected lorem', 'bar lorem', 'buz lorem'],
            ['expected ipsum', 'bar ipsum', 'buz ipsum'],
        ];
    }
    /**
     * @dataProvider provideDataForFooException
     */
    public function testFooException($paramBar, $paramBuz, $expectedException)
    {
        $myObject = new MyClass();
        $this->expectException($expectedException);
        $myObject->foo($paramBar, $paramBuz);
    }
    public function provideDataForFooException()
    {
        return [
            ['expected exception', 'bar invalid argument', '\My\Exception\Fully\Qualified\Name'],
        ];
    }
}
  1. 扩展解决方案

a. 一个测试方法和使用Reflection API。

我们只有一个测试方法。数据提供程序方法返回一个数组,其中对于$expected测试方法输入的两个元素可以是Exceptions。如果$expected是一个Exception,我们使用expectException(...)来处理这种情况,否则作为“正常”的测试用例。

b. 一个测试方法和使用“exception”标志。

理论上,一个方法可以return一个Exception。为了考虑这种情况,我们必须引入一个像“testItForException”这样的标志,并将此信息提供给测试方法。它也可以是由数据提供程序方法返回的另一个元素,例如exception(然后在测试方法中:if(! (empty($exception)) { test it as normal } else {expect exception}))。


2

除了注释外,您还可以使用$this->setExpectedExceptionRegExp()和参数

来进行设置。

$exceptionName — mixed (class name or exception instance)
$exceptionMessageRegExpstring (optional regular expression)
$exceptionCodeinteger (optional exception code)

注意:PHPUnit 5.2已经弃用了旧的setExpectedException()方法。

这意味着,你现在可以通过数据提供者传递一个异常类名。如果它不为空,就调用setExpectedExceptionRegExp()方法。

与注释相比,该方法的另一个优点是,如果你不在测试开始时调用该方法,你可以更具体地指定期望的异常出现的位置


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接