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

Iva*_*tov 5 php unit-testing zend-framework

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

$this->getInvokeArg('bootstrap')->getResource('foo');
Run Code Online (Sandbox Code Playgroud)

这适用于生产(浏览到相应的网页时).但是,在测试包含此代码的控制器操作时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();
Run Code Online (Sandbox Code Playgroud)

小智 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);

       }
}
Run Code Online (Sandbox Code Playgroud)

然后你使用如下:


class MyControllerTest extends My_ControllerTestCase
{

}

Run Code Online (Sandbox Code Playgroud)

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

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

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


jas*_*son 4

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

问题在于,这Zend_Test_PHPUnit_ControllerTestCase是为了对控制器进行单元测试。它尝试使用框架其余部分的很少的依赖项,并且它不会自动运行/引导/任何(并且不知道)您的较大应用程序。

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

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

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

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

public $bootstrap = '/path/to/bootstrap/file.php'
Run Code Online (Sandbox Code Playgroud)

对于使用 的应用程序来说,这是一个不错的选择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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

我建议重写dispatchTestCase 的方法,以确保它接收引导程序。(这肯定会起作用)。

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

想想看,您也可以这样做setUp

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