问题
Someone submitted a pull request to a library of mine wherein a parameter was made optional by replacing something like function doSomething($var)
with function doSomething($var = 'whatever')
.
So I added a unit test to make sure that an error would be issued if you didn't pass enough variables to the method. To catch this I was using the PHPUnit annotation @expectedException
. For PHP 7.0 the expected exception is PHPUnit_Framework_Error_Warning
but for PHP 7.1+ the expected exception is ArgumentCountError
. This presents a small problem. I can make the tests pass PHP 7.0 and earlier or pass PHP 7.1 and later. I can't make them support both.
Another PHPUnit annotation is @requires
but it seems like that only lets you restrict tests to a minimum PHP version - not to a maximum PHP version. eg. if I do @requires PHP 7.1
that'd mean that PHP 7.1 is the minimum version of PHP required to run the test but that there's no way to make PHP 7.0 the maximum version to run a test.
I thought doing @expectedException Exception
would work (since presumably PHPUnit_Framework_Error_Warning
and ArgumentCountError
both extend Exception but that does not appear to be the case either.
It'd be cool if I could do something like @expectedException PHPUnit_Framework_Error_Warning|ArgumentCountError
but nothing in the PHPUnit docs leads me to believe that I can and https://github.com/sebastianbergmann/phpunit/issues/2216 makes it sound like that can't be done period.
Maybe I should just remove this particular unit test all together?
回答1:
You can use the expectException()
method call, instead of the @expectedException
annotation. Using the method call is recommended anyway.
Conditionals in tests are usually a bad idea as tests should be straightforward, but if you insist you could implement the following:
public function testIt()
{
if (PHP_VERSION_ID >= 70100) {
$this->expectException(ArgumentCountError::class);
} else {
$this->expectException(PHPUnit_Framework_Error_Warning::class);
}
// ...
}
You could also implement two separate test cases and skip one or the other based on the PHP version:
public function testItForPHP70()
{
if (PHP_VERSION_ID >= 70100) {
$this->markTestSkipped('PHPUnit_Framework_Error_Warning exception is thrown for legacy PHP versions only');
}
$this->expectException(PHPUnit_Framework_Error_Warning::class);
// ...
}
public function testItForPHP71AndUp()
{
if (PHP_VERSION_ID < 70100) {
$this->markTestSkipped('ArgumentCountError exception is thrown for latest PHP versions only');
}
$this->expectException(ArgumentCountError::class);
// ...
}
来源:https://stackoverflow.com/questions/48189512/catching-argumentcounterror-and-phpunit-framework-error-warning