PHP的所有测试都失败了致命错误:无法重新声明类


All Tests fails with PHP Fatal error: cannot redeclare class

我得到一个奇怪的行为与PHPUnit,我不知道如果我做错了什么,或者如果它是一个bug从测试框架。以下是我的例子:

我的项目有几个类:BsInput, BsEmail, bshiden, BsNumber。BsEmail, bshiden和BsNumber扩展了BsInput。所有类都有单元测试类(bsinputttest用于BsInput, BsEmailTest用于BsEmail,等等)。

每个单独执行的单元测试都很好。

现在,如果我尝试在我的项目中运行所有测试,我得到一个错误和消息"PHP致命错误:不能在/some/path/to/b.p p上重新声明类B "。

每个文件的内容如下:

BsInput.php

require_once __DIR__ . "/BsInputControl.php";
class BsInput extends BsInputControl {
    ...
}

BsEmail.php

require_once __DIR__ . "/BsInput.php";
class BsEmail extends BsInput {
    ...
}

BsHidden.php

require_once __DIR__ . "/BsInput.php";
class BsHidden extends BsInput {
    ...
}

BsNumber.php

require_once __DIR__ . "/BsInput.php";
class BsNumber extends BsInput {
    ...
}

BsInputTest.php

require_once "../colibri/bs/BsInput.php";
class BsInputTest extends PHPUnit_Framework_TestCase {
    ...
}

BsEmailTest.php

require_once "../colibri/bs/BsEmail.php";
class BsEmailTest extends PHPUnit_Framework_TestCase {
    ...
}

BsHiddenTest.php

require_once "../colibri/bs/BsHidden.php";
class BsHiddenTest extends PHPUnit_Framework_TestCase {
    ...
}

BsNumberTest.php

require_once "../colibri/bs/BsNumber.php";
class BsNumberTest extends PHPUnit_Framework_TestCase {
    ...
}

最后一件让我抓狂的事:如果我注释掉BsHidden.php和BsHiddenTest.php中的所有代码,PHPUnit的所有测试在BsNumber和下面的类上执行得很顺利!

有人已经看到类似的东西了吗?有没有什么线索可以帮我解决这个问题?

我尝试了一个丑陋的解决方案:在BsInput.php

中插入以下代码
var_dump(class_exists('BsInput', FALSE));
if (class_exists('BsInput', FALSE)) { return; }

我得到这个结果:

bool(true)
PHP Fatal error: Cannot redeclare class BsInput in /.../BsInput.php on line 87

到目前为止,我已经研究了很多问题,包括上面的问题,但到目前为止,我还没有找到任何解决方案。

    PHPUnit一次加载所有类。导致PHP致命错误:不能重新声明类
  • PHPUnit Test Suite -不能重新声明类mock &具体类
  • "致命错误:不能重新声明类"... 但是类没有被声明

我也尝试将PHPUnit更新到最新版本(4.6),但没有成功。

我的平台是:Mac OS X 10.10PHP 5.5.20PHPUnit) 4.6.6Netbeans 8.0.2

有线索吗?

在试图解决这个问题后,我终于删除了我的BsHidden.php文件,附加的测试文件并完全重新创建了它们(我的意思是与我复制/粘贴的内容完全相同)…现在它成功了!这让我想到了PHP和PHPUnit之间的某个bug。

然而,一个快速&肮脏的解决方案似乎是:

  1. 复制粘贴文件和单元测试文件内容到另一个文件
  2. 删除有问题的文件和单元测试文件(如果有)
  3. 重新创建文件和单元测试文件并粘贴内容

我终于确定了我的问题。似乎有一个PHP错误,至少在我的平台上是这样。

PHP的手册说(http://php.net/manual/en/function.include-once.php) PHP4中的名称解析在不区分大小写的系统上是不区分大小写的,而PHP5处理这样的问题。

这是我在我的平台(Mac OS X 10.10, PHP 5.5)上得到的行为:

假设我有一个文件A.php,定义了一个A类和以下代码:

<?php
require_once 'A.php';
require_once 'a.php';
?>

第二个require_once触发Can not redeclare class error。所以在Mac OS X上的PHP5.5中,至少名称解析是不区分大小写的,但是PHP仍然认为它们是不同的文件

如果你只是使用class_exists,那么像这样使用它:

if (!class_exists('BsInput', FALSE)) { 
    class BsInput extends BsInputControl {
        // ToDo
    }
}

我不知道为什么会产生这个错误-你是否在 require_一次显式地使用 ?