PHPUnit has a very useful feature @dataProvider
, that allows to test multiple cases of a method. It also has another cool annotation -- @expectedException
to ensure the application throws a correct Exception
at a defined place.
I'm currently testing a method against multiple edge cases and would like to combine these two features like this (not working code):
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'],
];
}
}
Is possible / How to use @expectedException
as one of the cases, when using @dataProvider
?
PHPUnit doesn't provide this combination. But this can be implemented with a simple trick:
Separate test methods for normal and exception testing.
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'],
];
}
}
a. One test method and using the Reflection API.
We have only one test method. The data provider method returns an array, where to elements for the $expected
test method input can be Exceptions
. If the $expected
is an Exception
we handle this case with expectException(...)
, otherwise as a "normal" test case.
b. One test method and using an "exception" flag.
Theoretically a method can return
an Exception
. To consider this case we have to introduce a flag like "testItForException" and provide this information to the test method. It also can be a further element, e.g. exception
, in the array returned by the data provider method (and then in the test method: if(! (empty($exception)) { test it as normal } else {expect exception})
).
Instead of the annotation you can also use $this->setExpectedExceptionRegExp()
with the arguments
$exceptionName — mixed (class name or exception instance)
$exceptionMessageRegExp — string (optional regular expression)
$exceptionCode — integer (optional exception code)
Note: The old setExpectedException()
method has been deprecated in PHPUnit 5.2
This means, you can pass an exception class name via data provider. If it is not empty, call setExpectedExceptionRegExp()
Another advantage of the method over the annotation is that you can be more specific about where the exception is expected, if you don't call the method at the beginning of the test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With