单元测试Zend控制器模拟模型和服务
问题描述:
我读过很多Zend控制器测试教程,但我找不到解释如何测试使用模型和嘲笑这些模型的控制器。单元测试Zend控制器模拟模型和服务
我有以下控制措施: -
function indexAction(){
// Get the cache used by the application
$cache = $this->getCache();
// Get the index service client and model
$indexServiceClient = new IndexServiceClient($this->getConfig());
$indexModel = $this->_helper->ModelLoader->load('admin_indexmodel', $cache);
$indexModel->setIndexServiceClient($indexServiceClient);
// Load all the indexes
$indexes = $indexModel->loadIndexes();
$this->view->assign('indexes', $indexes);
}
目前,我有一个非常基本的测试案例: -
public function testIndexActionRoute() {
$this->dispatch('/admin/index');
$this->assertModule('admin', 'Incorrect module used');
$this->assertController('index', 'Incorrect controller used');
$this->assertAction('index', 'Incorrect action used');
}
这个测试工作,但它调用了真正的模型和服务,这有时意味着它超时并在测试环境中失败。为了正确地进行单元测试,我需要对IndexServiceClient和IndexModel进行嘲笑和期望 - 这是如何完成的?
答
好吧,由于我在这里看到的回复并不多,我会尝试添加我的2cents(可能有争议)。 下面写的答案是我的IHMO和非常主观(我认为不是很有用,但我们在这里我们去)
我认为控制器不是一个很好的适合单元测试。您的业务逻辑层,模型等是一致的。 控制器与UI连接并将系统集成在一起可以这么说 - 因此对我来说它们更适合集成和UI测试 - 这是Selenium等软件包所使用的。
在我看来,测试应该很容易实现,以便测试实施的总体工作量足以获得回报。对我来说,连接控制器的所有依赖关系似乎(我的知识当然有限)有点太多了。
想想它的另一种方式是 - 控制器中实际发生了什么。同样,IHMO应该主要是业务逻辑和用户界面之间的胶水级别。如果你将许多业务逻辑放入控制器中,将会产生不利影响(例如,它不会轻易无法统计)。
这是当然的各种理论。希望有人能提供更好的答案,并且实际展示如何轻松连接控制器进行单元测试!
答
一位同事提出的一种可能的解决方案是使用Zend Controller Action Helper注入模拟依赖关系。这应该在理论上工作,但我还没有广泛地测试这种方法
这是这样做的一个例子。
class Mock_IndexModel_Helper extends Zend_Controller_Action_Helper_Abstract {
private $model;
public function __construct($model) {
$this->model = $model;
}
/**
* Init hook
*/
public function init() {
$this->getActionController()->setIndexModel($this->model);
}
}
class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase {
public $bootstrap = BOOTSTRAP;
public function setUp(){
parent::setUp();
}
/**
* Test the correct module/controller/action are used
*/
public function testIndexAction() {
$mockIndexModel = $this->getMock("IndexModel");
Zend_Controller_Action_HelperBroker::addHelper(new Mock_IndexModel_Helper($mockIndexModel));
$this->dispatch('/admin/index');
$this->assertModule('admin', 'Incorrect module used');
$this->assertController('index', 'Incorrect controller used');
$this->assertAction('index', 'Incorrect action used');
}
}
在与我的同事们讨论后,得出了同样的结论。使用适当的模拟对控制器进行单元测试需要付出很大的努力,回报很少。尤其是我们的模型层完成了大部分工作,并且具有广泛的测试覆盖范围,而控制器非常薄。 – 2009-11-12 11:09:08