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

时间:2009-11-10 12:23:59

标签: unit-testing zend-framework

我已经阅读了很多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进行模拟和期望 - 这是如何完成的?

2 个答案:

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