在Zend_Test工具中执行Zend Framework控制器时设置正确的InvokeArg

时间:2009-08-04 10:31:11

标签: php unit-testing zend-framework

根据this邮件列表讨论,访问Zend MVC控制器中的应用程序资源的推荐方法是:

$this->getInvokeArg('bootstrap')->getResource('foo');

这适用于制作(浏览到相应的网页时)。但是,在使用Zend_Test_PHPUnit_ControllerTestCase测试包含此代码的控制器操作时,我得到:

PHP致命错误:在第12行的... / application / controllers / IndexController.php中的非对象上调用成员函数getResource()

在介绍getInvokeArg之前,测试运行得很好。问题是,如何在测试工具中使用“推荐”的方式访问资源?

刚检查:$this->getFrontController()->getParam('bootstrap')->getResource('foo')也不起作用。

更新:我用phpunit --bootstrap ./scripts/application_bootstrap.php ...调用应用程序引导程序,我知道它执行正常。

我有:

$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);

$application->bootstrap();

2 个答案:

答案 0 :(得分:9)

当使用需要引导程序的控制器插件时,我遇到了同样的问题。

基本上我创建了一个抽象类并从中继承。


abstract class My_ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase
{
    protected $application;

    public function setUp()
    {


        $this->bootstrap = array($this, 'appBootstrap');


        return parent::setUp();
    }

    public function appBootstrap()
       {

        $this->application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/config/app.ini');

        $this->application->bootstrap();

        $bootstrap = $this->application->getBootstrap();

        $front = $bootstrap->getResource('FrontController');

        $front->setParam('bootstrap', $bootstrap);

       }
}

然后使用如下:


class MyControllerTest extends My_ControllerTestCase
{

}

我还记录了一个请求,让此功能成为ZF的一部分

[ZF-7373] :( http://framework.zend.com/issues/browse/ZF-7373) -

发表评论有助于强调这一点。

答案 1 :(得分:4)

编辑:对不起,我第一次错过了你的问题部分(还没有咖啡!)。我已经编辑了答案。

问题在于Zend_Test_PHPUnit_ControllerTestCase是指单元测试控制器。它试图从框架的其余部分使用非常的几个依赖项,它不会自动运行/ bootstrap /任何(并且不知道)你的大型应用程序。

基本上,getResouce不起作用,因为你的引导程序不存在。

如果您浏览Zend_Test_PHPUnit_ControllerTestCase,您会看到它手动设置并使用Zend_Controller_Front,并为每个测试初始化​​自己的请求/响应对象。它试图尽可能多地进行单元测试,而不是功能测试或集成测试。

要解决您的问题,您必须告诉测试套件如何来引导您的应用程序。有几种方法可以实现这一目标。

一,您可以将文件分配给测试类的公共bootstrap属性。

public $bootstrap = '/path/to/bootstrap/file.php'

对于使用Zend_Application的应用程序,这是一个不错的选择。

或者,通过向bootstrap属性提供回调:

public function setUp()
{
    // Use the 'start' method of a Bootstrap object instance:
    $bootstrap = new Bootstrap('test');
    $this->bootstrap = array($bootstrap, 'start');
    parent::setUp();
}

注意:如果覆盖它,则调用父setUp方法非常重要。

编辑2:好的, 实际上是在引导你的应用程序。所以,你已经完成了上述工作,但仍然没有运气。

我建议覆盖TestCase的dispatch方法,以确保它正在接收引导程序。 (这肯定会起作用。)

public function dispatch($url = null)
{
    $this->getFrontController()->setParam('bootstrap', $yourBootstrap);
    parent::dispatch($url);
}

想想看,你也可以在setUp中做到这一点。

这将允许测试套件正确模仿由Zend_Application构造的前端控制器的行为。访问引导程序的两种方法现在都可以使用。