PHPUnit测试套件 - 无法重新声明模拟类和具体类

6
这里是我的问题。
我有一个测试套件,用于测试几个类。我的所有类都使用依赖注入。
我有一个名为scheduleHandler的类,通过了所有测试。然后我的另一个名为ruleHandler的类有一个方法需要一个scheduleHandler实例。我不想传递真正的scheduleHandler,所以我试图创建一个模拟的scheduleHandler进行注入。
我的问题是,因为scheduleHandler类在上面的测试套件中被测试过,当创建模拟时,我得到以下错误:
PHP Fatal error:  Cannot redeclare class scheduleHandler

如果我不使用测试套件,而是单独运行测试,一切都很好。有人知道解决这个问题的方法吗?

$mockScheduler = $this->getMock('scheduleHandler'); $mockScheduler = $this->getMock('scheduleHandler'); - SteveG
如果我在测试套件中改变顺序,它就能工作: $this->addTestSuite('scheduleHandlerTest'); $this->addTestSuite('ruleHandlerTest');非常奇怪... - SteveG
1
能否在 $this->getMock 调用之前加上 var_dump(class_exists('scheduleHandler', false));?只是为了看看我的假设是否有任何价值。 - edorian
1
你能确认 var_dump(get_class($this->getMock('scheduleHandler'))) 会给你类似于 scheduleHandlerTest_<随机哈希> 的东西吗? - Mike B
@Mike B:是的,我确实得到了这个结果:object(Mock_scheduleHandler_47ab6dd0)#208 (3) { ["invocationMocker:protected"]=> NULL ["_observer:private"]=> array(0) { } ["_db:private"]=> NULL } - SteveG
显示剩余2条评论
3个回答

5

到目前为止,我最好的猜测是:

var_dump(class_exists('scheduleHandler', false)); 

如果返回值是false,那就意味着该类还不存在。如果在phpunit尝试从该类扩展时,你的自动加载程序找不到该类,phpunit会自行创建此类。

如果在后续某个时刻,您从其他地方需要真正的scheduleHandler类,则这两个类将冲突。

为了测试这一点,请确保在创建模拟对象之前已经引入了真正的scheduleHandler类。


是的,正如之前提到的那样,在测试套件中,实际的scheduleHandler位于具有模拟对象的ruleHandler之上时,它确实可以工作。我在这些测试中没有使用自动加载器。它确实可以工作,但如果更改顺序,我不喜欢它会出现错误的情况。干杯! - SteveG
所以我的建议是在创建模拟对象之前先要求一次真实的类。我不知道还有什么其他方法可以避免这种行为。 - edorian
是的,这大概就是我能做的全部了。等我有更多时间时,我会重新审视并尝试找出导致重新声明的原因。感谢大家的参与! - SteveG
1
重新声明是由于Edorian所述的原因引起的:在告诉PHPUnit声明类本身之后(通过在类不存在之前调用getMock()),您手动包含了类的模块。自动加载程序将为您节省大量的精力和头痛,不使用它只是纯粹的愚蠢。 :) - David Harkness

3

尝试在模拟创建中使用命名空间。如果您在项目代码中没有使用它们,那么希望它会覆盖全局命名空间并不会引起冲突。

$this->getMock('\SomeTestingFramework\SomeTestClass\scheduleHandler');


0
尝试使用$this->getMock('scheduleHandler', array(), array(), '', false)。这将导致PHPUnit跳过调用scheduleHandler::__construct,这可能是通过加载两次类而引起错误的原因。

PHP 致命错误:无法重新声明类 scheduleHandler,路径为 /var/www/fleetManagement/models/scheduleHandler.class.php。 - SteveG
你能否在getMock调用后添加类似于echo '!!!'; die;的内容,以查看该行是否导致了致命错误,或者是发生在稍后? - Tgr
以上内容不会被输出,致命错误会先发生。 - SteveG
很奇怪 - 当第五个参数设置为false时,getMock()不应该调用您的代码中的任何内容,因此它不应该导致致命错误。也许您正在使用一个非常旧的PHPUnit版本,它没有这个选项 - 您可以检查一下 phpunit --version?您还可以尝试调用 $this->getMock('scheduleHandler', array(), array(), '', false, false, false) 来禁用自动加载和调用 __clone - 这两者在这里都不相关,但值得一试。 - Tgr
谢谢。我尝试过了,结果还是一样。这是版本输出:- PHPUnit 3.5.15 by Sebastian Bergmann。 - SteveG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接