Cannot redeclare class error when generating PHPUnit code coverage report
Starting a project with Zend Framework 1.10 and Doctrine 2 (Beta1). I am using namespaces in my own library code.
When generating code coverage reports I get a Fatal Error about Redeclaring a class. To provide more info, I've commented out the xdebug_disable() call in my phpunit executable so you can see the function trace (disabled local variables output because there was too much output).
Here's my Terminal output:
$ phpunit PHPUnit 3.4.12 by Sebastian Bergmann. ........ Time: 4 seconds, Memory: 16.50Mb OK (8 tests, 14 assertions) Generating code coverage report, this may take a moment.PHP Fatal error: Cannot redeclare class Cob\Application\Resource\HelperBroker in /Users/Cobby/Sites/project/trunk/code/library/Cob/Application/Resource/HelperBroker.php on line 93 PHP Stack trace: PHP 1. {main}() /usr/local/zend/bin/phpunit:0 PHP 2. PHPUnit_TextUI_Command::main() /usr/local/zend/bin/phpunit:54 PHP 3. PHPUnit_TextUI_Command->run() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:146 PHP 4. PHPUnit_TextUI_TestRunner->doRun() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:213 PHP 5. PHPUnit_Util_Report::render() /usr/local/zend/share/pear/PHPUnit/TextUI/TestRunner.php:478 PHP 6. PHPUnit_Framework_TestResult->getCodeCoverageInformation() /usr/local/zend/share/pear/PHPUnit/Util/Report.php:97 PHP 7. PHPUnit_Util_Filter::getFilteredCodeCoverage() /usr/local/zend/share/pear/PHPUnit/Framework/TestResult.php:623 Fatal error: Cannot redeclare class Cob\Application\Resource\HelperBroker in /Users/Cobby/Sites/project/trunk/code/library/Cob/Application/Resource/HelperBroker.php on line 93 Call Stack: 0.0004 322888 1. {main}() /usr/local/zend/bin/phpunit:0 0.0816 4114628 2. PHPUnit_TextUI_Command::main() /usr/local/zend/bin/phpunit:54 0.0817 4114964 3. PHPUnit_TextUI_Command->run() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:146 0.1151 5435528 4. PHPUnit_TextUI_TestRunner->doRun() /usr/local/zend/share/pear/PHPUnit/TextUI/Command.php:213 4.2931 16690760 5. PHPUnit_Util_Report::render() /usr/local/zend/share/pear/PHPUnit/TextUI/TestRunner.php:478 4.2931 16691120 6. PHPUnit_Framework_TestResult->getCodeCoverageInformation() /usr/local/zend/share/pear/PHPUnit/Util/Report.php:97 4.2931 16691148 7. PHPUnit_Util_Filter::getFilteredCodeCoverage() /usr/local/zend/share/pear/PHPUnit/Framework/TestResult.php:623
(I have no idea why it shows the error twice...?)
And here is my phpunit.xml:
<phpunit bootstrap="./code/tests/application/bootstrap.php" colors="true">
<!-- bootstrap.php changes directory to trunk/code/tests,
all paths below are relative to this directory. -->
<testsuite name="My Promotions">
<directory>./</directory>
</testsuite>
<filter>
<whitelist>
<directory suffix=".php">../application</directory>
<directory suffix=".php">../library/Cob</directory>
<exclude>
<!-- By adding the below line I can remove the error -->
<file>../library/Cob/Application/Resource/HelperBroker.php</file>
<directory suffix=".phtml">../application</directory>
<directory suffix=".php">../application/doctrine</directory>
<file>../application/Bootstrap.php</file>
<directory suffix=".php">../library/Cob/Tools</directory>
</exclude>
</whitelist>
</filter>
<logging>
<log type="junit" target="../../build/reports/tests/report.xml" />
<log type开发者_高级运维="coverage-html" target="../../build/reports/coverage" charset="UTF-8"
yui="true" highlight="true" lowUpperBound="50" highLowerBound="80" />
</logging>
</phpunit>
I have added a tag inside the which seams to hide this problem. I do have another application resource but it doesn't seam to have a problem (the other one is a Doctrine 2 resource). I'm not sure why it is specific to this class, my entire library is autoloaded so their isn't any include/require calls anywhere. I guess it should be noted that HelperBroker is the first file in the filesystem stemming out from library/Cob
I am on Snow Leopard with the latest/recent versions of all software (Zend Server, Zend Framework, Doctrine 2 Beta1, Phing, PHPUnit, PEAR).
General answer to wrap this problem up:
This error message usually points to a problem with auto loading and or require statements.
During code coverage report generation phpunit is require
ing every *.php
that is in <whitelist>
. This can be turned off using addUncoveredFilesFromWhitelist=false
as a
parameter but it is recommended to keep this on.
Possible reasons
What tends to happen in these cases is that one of the files has a require
statement that requires an already loaded class again (as it is not a require_once).
Other reasons can be
the duplicate definition of classes (one for debugging one for production, should be solved by inheritance not by loading the right php file)
Inconsistent capitalization leading to errors in the php code like:
if( !$classesLoaded['ThIsClass']) require_once(...);
in multiple places with different capitalizations.The class not getting loaded at all in the tests but a mock object was created with the name of the then loaded class. Those can collide and lead to that error too
One other thing to check (particularly if you are working with a VM) is whether a file has been renamed but still exists in the original form. eg. fooMapper.php renamed to FooMapper.php (eg. via SVN update), your IDE detects the new file and sends it to the VM. You now have both versions on your VM even if your IDE locally only shows one. Beware.
A quick workaround may be to add an if statement at the beggining of your class declaration in order to avoid redeclaration when running phpunit (if, and only if, that's the only class you're having problems with)
if (!class_exists("class_name")) {
// declare the class
class class_name
{
//...
}
}
I had a similar problem, because I used all the files for the coverage instructions. When I set concrete directory and needed files my problem was solved.
I think your problem is here:
<testsuite name="My Promotions">
<directory>./</directory>
</testsuite>
Here you required all the files and directories.
Try this case to require only tests (or set your folders):
<testsuite name="My Promotions">
<directory>tests</directory>
</testsuite>
You also can use prefixes, suffixes and files:
- https://phpunit.readthedocs.io/en/9.5/configuration.html#the-directory-element
- https://phpunit.readthedocs.io/en/9.5/configuration.html#the-file-element
This happened to me because I had a typo in my @covers declaration. Notice the extra \ in the first line.
App\Controller\\Account\UsersController::forgotPassword()
VS
App\Controller\Account\UsersController::forgotPassword()
I found that I received this error when an incorrect @coversDefaultClass
(same likely applies to @covers
too) annotation was used. In my case it was \Path\To\\Class
(with double '\') which was messing with the require calls.
精彩评论