Unit testing 使用模拟模型和服务对Zend控制器进行单元测试

Unit testing 使用模拟模型和服务对Zend控制器进行单元测试,unit-testing,zend-framework,Unit Testing,Zend Framework,我已经阅读了很多Zend controller测试教程,但我找不到一本解释如何测试使用模型的控制器并模拟这些模型的教程 我有以下控制器操作:- function indexAction(){ // Get the cache used by the application $cache = $this->getCache(); // Get the index service client and model $indexServiceClient = new Inde

我已经阅读了很多Zend controller测试教程,但我找不到一本解释如何测试使用模型的控制器并模拟这些模型的教程

我有以下控制器操作:-

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进行模拟和期望-这是如何做到的?

好吧,因为我在这里看到的回复不多,我将尝试添加我的2个元素(可能有争议)。 下面写的答案是我的IHMO,非常主观(我认为不是很有用,但我们还是来吧)

我认为控制器不适合单元测试。您的业务逻辑层、模型等是unitestable。 控制器与UI相连,可以说是将系统连接在一起——因此对我来说,它们更适合集成和UI测试——这是Selenium等软件包的用途

在我看来,测试应该很容易实现,这样测试实现的全部努力就足以满足它的回报。连接控制器的所有依赖项对我来说(当然我的知识有限)有点太繁重了

另一种思考方式是——控制器中实际发生了什么。同样,IHMO认为它主要是业务逻辑和UI之间的粘合层。如果您将大量业务逻辑放入控制器,则会产生不利影响(例如,它不容易统一)


这当然是一种理论。希望有人能提供一个更好的答案,并实际演示如何轻松地为单元测试连接控制器

一位同事提出的一种可能的解决方案是使用Zend Controller操作助手来注入模拟依赖项。这在理论上应该是可行的,但我还没有对这个方法进行广泛的测试

这里有一个这样做的例子

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');
    }    
}

在与我的同事讨论后,得出了相同的结论。在具有适当模拟的控制器中进行单元测试需要花费大量精力,但回报甚微。这一点尤其正确,因为我们的模型层完成了大部分工作,并且具有广泛的测试覆盖范围,而控制器非常薄。