我是Zend Framework和PHPUnit的新手。我正在将遗留应用程序转换为MVC架构,并且正在尝试编写单元测试。我对单元测试概念有点熟悉,但总的来说,它一直困扰着存根和嘲弄。例如,请考虑以下
在控制器操作中,我试图测试我传入的成员ID。然后我使用ID初始化成员对象。然后,我调用与成员对象关联的多个方法,并将返回值分配给视图对象。
class A extends Zend_Controller_Action {
public function viewAction() {
$member = new Member($this->getRequest()-> getParam('id'));
//perform various calls on the member object
$gender = $member->getGender();
...
//assign the return values to the view object
$this->view->assign('gender',$gender);
...
}
}
如何在我的测试中模拟$ member变量,以便我可以自定义方法返回值?
如果我的理解不正确,我会非常感谢一些指导。
谢谢!
答案 0 :(得分:6)
如果我理解正确,你就是在为这个行动写一个测试。在这种情况下,由于在方法内部创建了新实例,因此无法模拟$ member。这就是为什么我们都尽可能多地在对象图中尽可能多地浮动new
语句(DI)。
通常有一个特殊的PHPunit测试用例Zend_Test_PHPUnit来测试你的控制器。
但事实上,正确测试ZF控制器非常困难甚至不可能(意味着完全隔离)。您最好测试应用程序的其余部分,通用库等。
换句话说,在ZF1逻辑中,控制器是中央布线位置(在引导程序之后),传统上使用了许多new
语句。显然,这会导致不可测试性,因为每个创建而不是注入的实例都是不可修复的。
正如@vascowhite指出的那样,追求精益控制器也是一件好事。这意味着,尽可能多地将逻辑移动到模型层。这将导致更少的冗余(DRY)和更好的可测试性。
但要注意不要让你的模型膨胀。有时您可能希望将一些代码考虑到其他组件中。
另一个问题是你不能模拟前端控制器,因为它是一个单例。所以你真的没有很多选择来测试这样的动作。唯一的选择是注入成员实例或从注册表中获取它(也不是一个好主意)。
所以,鉴于所有这一点很明显,你无法完成动作测试的完全隔离。但是
ZF2将更容易测试。
答案 1 :(得分:1)
最好从功能测试覆盖控制器开始。在这种情况下,您可以绕过这个模拟问题并获得更好的测试覆盖率。控制器总是很难被单元测试覆盖,因为它们是强耦合的。
要使用ZF编写功能测试,请考虑使用Codeception:http://codeception.com/01-27-2012/bdd-with-zend-framework.html
此外,还有一些例子,如何对控制器进行单元测试。但是,从那时起,我建议在对它们进行功能测试后对单元测试控制器进行测试。
http://codeception.com/docs/06-UnitTestsAndBDD#TestingController