在动态分配的实例上模拟方法?

时间:2014-11-04 04:47:16

标签: php unit-testing mocking phpunit

背景:我正在为一些练习开发MVC框架,并希望确保所有内容都经过100%的单元测试。

当前的设置是拥有应用程序类的实例(Ex_App)。主脚本向Dispatcher / Router询问控制器名称。此控制器名称是实现Ex_Controller的类的名称。结果作为Ex_Dispatch_Result的实例返回。此结果使用Ex_App函数传递给invokeController($dispatchResult)实例。

这就是魔术发生的地方。以下列表摘录如下:

$controllerName = $dispatchResult->getControllerName();
... checks for validaty of class name ...
$controller = new $controllerName();
$controller->prepare($this);

我使用PHPUnit进行单元测试,并能够模拟调度结果,正确检查验证控制器的类名是否有效。问题是如何检查是否调用了准备。

我想做类似的事情:

$mockController = $this->getMockBuilder('Ex_Controller')
  ->setMockClassName('Invoke_Correct_Controller')
  ->getMock();
$mockController->expects($this->once())->method('prepare');

但是,由于在调用Invoke_Correct_Controller时创建了invokeController的新实例,因此它不会是此模拟,因此expects()调用完全无关紧要。

我可以让Ex_Dispatch_Result类负责返回一个控制器并对其进行测试,但在返回实例之前,我需要验证类名的正确性,在我看来,责任应该在{{{ 1}}类而不是"哑壳" Ex_App上课。

PHPUnit框架中是否有我可以用来测试代码的东西,或者一些可以在我的实例中使用的有用模式?我觉得绕过控制器名称比从一开始就传递控制器实例更好,需要初始化每个可能的控制器。所以,我有点想要传递名称并使用Ex_Dispatch_Result作为控制器实例的工厂。

也许我只是过度思考这个问题的一部分,但有时会发生这种情况。这就是为什么第三方的新面貌经常起作用的原因: - )

1 个答案:

答案 0 :(得分:2)

你可以做几件事:

  • 提取控制器创建逻辑以分离类,例如ControllerFactory,然后模拟控制器工厂实例,以便它返回你的$ mockController。
  • 提取控制器创建逻辑以分离方法并使用部分模拟。
  • 从$ dispatchResult-> getControllerName()返回$ mockController,这可能需要模拟$ dispatchResult甚至其他东西。

如果您需要更详细的答案,请提供更多类和方法的代码示例。