How to solve PHPUnit issues in Symfony 3.2 applications

The Problem

If your application uses Symfony 3.2 and you execute PHPUnit via its PHAR file, you'll end up with the following error message:

$ cd my-project/
$ php phpunit.phar

PHPUnit 5.6.2 by Sebastian Bergmann and contributors.

PHP Fatal error:  Undefined class constant 'PARSE_CONSTANT' in
Loader/YamlFileLoader.php on line 396

The Solution

In Symfony 3.2 applications you can't use the PHAR file of PHPUnit and you must use instead the PHPUnit Bridge. First, if this component is not installed in your project, install it as follows:

$ cd my-project/
$ composer require --dev symfony/phpunit-bridge

Then, execute your tests with the following command (the first time it will take some extra time because it must build the PHPUnit archive):

$ cd my-project/
$ ./vendor/bin/simple-phpunit
# depending on your Symfony config, this can also be:
# $ ./bin/simple-phpunit

The Explanation

This error happens when the code under test shares dependencies with PHPUnit but requires different versions than the ones bundled in the PHPUnit PHAR. In Symfony applications this happens with the Yaml component.

PHPUnit is working to solve this issue by adding a custom prefix to all their PHP namespaces automatically (see details) but they haven't achieved that yet.

Meanwhile, the best working solution is to make use of the PHPUnit Bridge component. In addition to not embedding conflicting dependencies (such as symfony/yaml) it provides some additional features:

  • It automatically selects the best version to run: PHPUnit 4.x when run with PHP <=5.5 and PHPUnit 5.x when run with PHP >=5.6;
  • It parallelizes test suites execution when given a directory as argument.

In the Symfony project we've suffered this problem for a long time. That's why you can see the use of simple-phpunit in the .travis.yml config file of lots of bundles and libraries, such as SensioFrameworkExtraBundle and Sami.

In addition to symfony/yaml you can also suffer this problem when using prophecy. Read the PHPUnit Bridge docs to learn more about this and the use of the SYMFONY_PHPUNIT_REMOVE environment variable.



But you should correct something: for Symfony 3, composer's "bin-dir" is the default "vendor/bin/" one, so we can't do "bin/simple-phpunit", we have to do "./vendor/bin/simple-phpunit" instead :)
@Alex I've made some changes in the original post. Thanks!
It is OK thanks. Note that the php zip extension is required for this to work.
Works great on the command line!

Sadly I have not yet found out how to run this from PHPStorm.

Does anyone have an idea?

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.