我已经阅读了很多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进行模拟和期望 - 这是如何完成的?
答案 0 :(得分:4)
好吧,因为我在这里看到的回复不多,所以我会尝试添加我的2cents(可能是有争议的)。 下面写的答案是我的IHMO,非常主观(我觉得不是很有用,但我们还是去了)
我认为控制器不适合单元测试。您的业务逻辑层,模型等是不可复制的。 控制器与UI连接并将系统结合在一起可以说 - 因此对我来说它们更适合集成和UI测试 - 像Selenium这样的软件包用于。
在我看来,测试应该很容易实现,以便测试实现的总体努力足以使其返回。对于控制器来说,接线所有依赖关系对我来说(当然我的知识有限)有点太多的任务。
另一种思考方式是 - 控制器中实际发生了什么。 IHMO它应该主要是您的业务逻辑和UI之间的胶水级别。如果您将大量业务逻辑放入控制器中,则会产生负面影响(例如,它不会很容易变得不稳定......)。
这当然是一种理论。希望有人可以提供更好的答案,并实际展示如何轻松连接控制器进行单元测试!
答案 1 :(得分:2)
同事提出的一个可能的解决方案是使用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');
}
}