Have you been working on phpunit/phpunit ? Are you a user of PhpStorm?

I have and I am, and until yesterday I have been struggling with setting up phpunit/phpunit as test framework for PhpStorm so I can run tests for phpunit/phpunit from within PhpStorm for phpunit/phpunit itself.

Use Composer autoloader

In any project that requires phpunit/phpunit as a development dependency, the setup is fairly simple: pick the Use Composer autoloader option and reference the path to vendor/autoload.php .

However, for phpunit/phpunit this will not work, as it does not have a dependency on itself:

Path to phpunit.phar (with downloaded phpunit.phar)

Ok, then, let’s try the option Path to phpunit.phar!

Looks like we need to download phpunit.phar here, so let’s head over to Getting Started with PHPUnit 8 and find out how to download phpunit.phar`.

Personally, I ran

$ wget -O ~/Sites/phpunit.phar https://phar.phpunit.de/phpunit.phar $ chmod +x ~/Sites/phpunit.phar

Next, I pick the Path to phpunit.phar option and specify the path to the previously downloaded phpunit.phar :

Looks like that worked fine, now let’s run the tests by right-clicking on phpunit.xml , and selecting the option Run ‘phpunit.xml’.

Great, the tests run! But they fail with

Testing started at 11:25 ... /usr/local/Cellar/php@7.2/7.2.17_1/bin/php /Users/am/Sites/phpunit --configuration /Users/am/Sites/sebastianbergmann/phpunit/phpunit.xml --teamcity PHPUnit 8.1.3 by Sebastian Bergmann and contributors. Runtime: PHP 7.2.17 with Xdebug 2.7.1 Configuration: /Users/am/Sites/sebastianbergmann/phpunit/phpunit.xml TypeError : Return value of PHPUnit\Framework\Constraint\Count::getCountOf() must be of the type integer or null, none returned phar:///Users/am/Sites/phpunit/phpunit/Framework/Constraint/Count.php:86 phar:///Users/am/Sites/phpunit/phpunit/Framework/Constraint/Count.php:44 phar:///Users/am/Sites/phpunit/phpunit/Framework/Constraint/Constraint.php:45 /Users/am/Sites/sebastianbergmann/phpunit/tests/unit/Framework/Constraint/CountTest.php:164 phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:1172 phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:854 phar:///Users/am/Sites/phpunit/phpunit/Framework/TestResult.php:685 phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:808 phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 phar:///Users/am/Sites/phpunit/phpunit/TextUI/TestRunner.php:601 phar:///Users/am/Sites/phpunit/phpunit/TextUI/Command.php:207 phar:///Users/am/Sites/phpunit/phpunit/TextUI/Command.php:163 PHP Fatal error: Class Mock_Exception_19a384fc contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ExceptionWithThrowable::getAdditionalInformation) in phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php(608) : eval()'d code on line 1 PHP Stack trace: PHP 1. {main}() /Users/am/Sites/phpunit:0 PHP 2. PHPUnit\TextUI\Command::main() /Users/am/Sites/phpunit:619 PHP 3. PHPUnit\TextUI\Command->run() phar:///Users/am/Sites/phpunit/phpunit/TextUI/Command.php:163 PHP 4. PHPUnit\TextUI\TestRunner->doRun() phar:///Users/am/Sites/phpunit/phpunit/TextUI/Command.php:207 PHP 5. PHPUnit\Framework\TestSuite->run() phar:///Users/am/Sites/phpunit/phpunit/TextUI/TestRunner.php:601 PHP 6. PHPUnit\Framework\TestSuite->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 PHP 7. PHPUnit\Framework\TestSuite->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 PHP 8. GeneratorTest->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 PHP 9. PHPUnit\Framework\TestResult->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:808 PHP 10. GeneratorTest->runBare() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestResult.php:685 PHP 11. GeneratorTest->runTest() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:854 PHP 12. GeneratorTest->testMockingOfThrowable() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:1172 PHP 13. PHPUnit\Framework\MockObject\Generator->getMock() /Users/am/Sites/sebastianbergmann/phpunit/tests/unit/Framework/MockObject/GeneratorTest.php:190 PHP 14. PHPUnit\Framework\MockObject\Generator->getObject() phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php:196 PHP 15. PHPUnit\Framework\MockObject\Generator->evalClass() phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php:562 PHP 16. eval() phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php:608 Fatal error: Class Mock_Exception_19a384fc contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ExceptionWithThrowable::getAdditionalInformation) in phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php(608) : eval()'d code on line 1 Call Stack: 0.0057 543992 1. {main}() /Users/am/Sites/phpunit:0 0.1437 9827856 2. PHPUnit\TextUI\Command::main() /Users/am/Sites/phpunit:619 0.1437 9827968 3. PHPUnit\TextUI\Command->run() phar:///Users/am/Sites/phpunit/phpunit/TextUI/Command.php:163 0.4764 23119992 4. PHPUnit\TextUI\TestRunner->doRun() phar:///Users/am/Sites/phpunit/phpunit/TextUI/Command.php:207 0.7250 23869248 5. PHPUnit\Framework\TestSuite->run() phar:///Users/am/Sites/phpunit/phpunit/TextUI/TestRunner.php:601 0.7466 23869440 6. PHPUnit\Framework\TestSuite->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 3.7839 25022328 7. PHPUnit\Framework\TestSuite->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 3.8201 25324600 8. GeneratorTest->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestSuite.php:761 3.8201 25324600 9. PHPUnit\Framework\TestResult->run() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:808 3.8202 25324600 10. GeneratorTest->runBare() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestResult.php:685 3.8204 25341232 11. GeneratorTest->runTest() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:854 3.8204 25341288 12. GeneratorTest->testMockingOfThrowable() phar:///Users/am/Sites/phpunit/phpunit/Framework/TestCase.php:1172 3.8204 25341288 13. PHPUnit\Framework\MockObject\Generator->getMock() /Users/am/Sites/sebastianbergmann/phpunit/tests/unit/Framework/MockObject/GeneratorTest.php:190 3.8209 25344136 14. PHPUnit\Framework\MockObject\Generator->getObject() phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php:196 3.8209 25344136 15. PHPUnit\Framework\MockObject\Generator->evalClass() phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php:562 3.8211 25350656 16. eval('class Mock_Exception_19a384fc extends Exception implements ExceptionWithThrowable, PHPUnit\Framework\MockObject\MockObject { private $__phpunit_invocationMocker; private $__phpunit_originalObject; private $__phpunit_configurable = []; private $__phpunit_returnValueGeneration = true; public function expects(\PHPUnit\Framework\MockObject\Matcher\Invocation $matcher): \PHPUnit\Framework\MockObject\Builder\InvocationMocker { return $this->__phpunit_getInvocationMocker()->expects($matcher); } public function method() { $any = new \PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount; $expects = $this->expects($any); return call_user_func_array([$expects, 'method'], func_get_args()); } public function __phpunit_setOriginalObject($originalObject): void { $this->__phpunit_originalObject = $originalObject; } public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration): void { $this->__phpunit_returnValueGeneration = $returnValueGeneration; } public function __phpunit_getInvocationMocker(): \PHPUnit\Framework\MockObject\InvocationMocker { if ($this->__phpunit_invocationMocker === null) { $this->__phpunit_invocationMocker = new \PHPUnit\Framework\MockObject\InvocationMocker($this->__phpunit_configurable, $this->__phpunit_returnValueGeneration); } return $this->__phpunit_invocationMocker; } public function __phpunit_hasMatchers(): bool { return $this->__phpunit_getInvocationMocker()->hasMatchers(); } public function __phpunit_verify(bool $unsetInvocationMocker = true): void { $this->__phpunit_getInvocationMocker()->verify(); if ($unsetInvocationMocker) { $this->__phpunit_invocationMocker = null; } } } ') phar:///Users/am/Sites/phpunit/phpunit/Framework/MockObject/Generator.php:608 Process finished with exit code 255

Looks like we have some issues here because we are using a different version of phpunit/phpunit for testing the version of phpunit/phpunit we have currently checked out.

Path to phpunit.phar (with phpunit binary)

While not obvious, there’s a rather simple solution that was suggested by Nicolas Hohm: pick the Path to phpunit.phar option and specify the path the phpunit binary in the root of the project!

Running the tests by right-clicking on phpunit.xml , and selecting the option Run ‘phpunit.xml’ now works like a charm!

Even better, when enabling Xdebug and selecting the option Run ‘phpunit.xml’ with Coverage, we can now easily identify areas of the code base which are obviously lacking tests - something we have been doing yesterday and today here at FLYERALARAM, where the 5th PHPUnit Code Sprint has been taking place.

Hope it helps!