ZF-Autoloader无法在Ubuntu上的UnitTests中工作

时间:2012-07-03 06:46:22

标签: zend-framework phpunit command-line-interface zend-autoloader

我遇到了关于在Ubuntu 12.04下对Zend-Framework应用程序进行单元测试的问题。项目结构是默认的zend应用程序,而模型定义如下

./application
  ./models
    ./DbTable
      ./ProjectStatus.php (Application_Model_DbTable_ProjectStatus)
    ./Mappers
      ./ProjectStatus.php (Application_Model_Mapper_ProjectStatus)
    ./ProjectStatus.php   (Application_Model_ProjectStatus)

这里的问题是Zend特定的自动加载。这里的命名约定似乎是 Mappers 文件夹加载所有带 _Mapper 但不加载 _Mappers 的类。这是一些内部的Zend行为,到目前为止还不错。

在我的Windows机器上,phpunit运行没有任何问题,尝试启动所有这些类。

在我的Ubuntu机器上运行jenkins时,phpunit无法找到合适的类给我以下错误

Fatal error: Class 'Application_Model_Mapper_ProjectStatus' not found 
in /var/lib/jenkins/jobs/PAM/workspace/tests/application/models/Mapper/ProjectStatusTest.php
on line 39

错误似乎真的是Zend-Autoloader没有从ubuntu机器加载,但我无法弄清楚这是如何或为什么这样做。问题仍然是为什么会这样。我想我已经仔细检查了与zend自动加载的每个接触点,但我无法弄清楚这一点。我会粘贴 - 从我的角度来看相关的片段 - 并希望你们中的某个人对此有任何见解。

用于PHPUnit的Jenkins Snippet

 <target name="phpunit" description="Run unit tests with PHPUnit">
   <exec executable="phpunit" failonerror="true">
     <arg line="--configuration '${basedir}/tests/phpunit.xml' --coverage-clover '${basedir}/build/logs/clover.xml' --coverage-html '${basedir}/build/coverage/.' --log-junit '${basedir}/build/logs/junit.xml'" />
   </exec>
 </target>

./测试/ phpunit.xml

<phpunit bootstrap="./bootstrap.php">
   ... this shouldn't be of relevance ...
</phpunit>

./测试/ bootstrap.php中

<?php
// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

require_once 'Zend/Loader/Autoloader.php';    
Zend_Loader_Autoloader::getInstance();

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

我实际上认为问题出在你的“models / Mappers”文件夹中。它应该是“models / mappers”(全部小写),并且可以解释为什么它适用于Windows而不适用于Linux。

从Zend_Application_Module_Autoloader类中可以看到:

$this->addResourceTypes(array(
            'dbtable' => array(
                'namespace' => 'Model_DbTable',
                'path'      => 'models/DbTable',
            ),
            'mappers' => array(
                'namespace' => 'Model_Mapper',
                'path'      => 'models/mappers',
            ),

但是,根据我之前的回答,我仍然认为您需要引导应用程序以自动添加所有默认资源

答案 1 :(得分:1)

来自ZF手册:

  

创建模型和数据库表

     

在我们开始之前,让我们考虑一下:这些课程将在哪里生活,以及如何实现   我们找到了吗?我们创建的默认项目实例化了一个   自动加载磁带机。我们可以附加其他自动加载器,以便它知道   在哪里可以找到不同的类。通常,我们需要各种MVC   在同一棵树下分组的类 - 在这种情况下,应用程序/ -   并且大多数情况下使用共同的前缀。

     

Zend_Controller_Front 有一个“模块”的概念,它们是个体的   小型应用程序。模块模仿zf的目录结构   在application /下设置工具,其中的所有类都是   假设以公共前缀开头,即模块名称。应用/   本身就是一个模块 - “默认”或“应用程序”模块。因此,   我们要为此目录中的资源设置自动加载。

     

Zend_Application_Module_Autoloader 提供所需的功能   将模块下的各种资源映射到适当的   目录,并提供标准的命名机制。一个   默认情况下,在初始化期间创建类的实例   引导对象;您的应用程序引导程序将默认使用   模块前缀“Application”。因此,我们的模型,表格和表格   类都将以类前缀“Application _”开头。

由于默认情况下加载了Zend_Application_Module_Autoloader,因此您只需要根据此答案的示例来引导应用程序(您不必运行前端控制器)。

如果您不想引导应用程序,可以通过自己初始化Zend_Application_Module_Autoloader来短路资源加载:

$autoloader = new Zend_Application_Module_Autoloader();

从代码中可以看出,这个类的__construct调用了initDefaultResourceTypes(),包含了你正在寻找的所有好东西:

class Zend_Application_Module_Autoloader extends Zend_Loader_Autoloader_Resource
{
    /**
     * Constructor
     *
     * @param  array|Zend_Config $options
     * @return void
     */
    public function __construct($options)
    {
        parent::__construct($options);
        $this->initDefaultResourceTypes();
    }

    /**
     * Initialize default resource types for module resource classes
     *
     * @return void
     */
    public function initDefaultResourceTypes()
    {
        $basePath = $this->getBasePath();
        $this->addResourceTypes(array(
            'dbtable' => array(
                'namespace' => 'Model_DbTable',
                'path'      => 'models/DbTable',
            ),
            'mappers' => array(
                'namespace' => 'Model_Mapper',
                'path'      => 'models/mappers',
            ),
            'form'    => array(
                'namespace' => 'Form',
                'path'      => 'forms',
            ),
            'model'   => array(
                'namespace' => 'Model',
                'path'      => 'models',
            ),
            'plugin'  => array(
                'namespace' => 'Plugin',
                'path'      => 'plugins',
            ),
            'service' => array(
                'namespace' => 'Service',
                'path'      => 'services',
            ),
            'viewhelper' => array(
                'namespace' => 'View_Helper',
                'path'      => 'views/helpers',
            ),
            'viewfilter' => array(
                'namespace' => 'View_Filter',
                'path'      => 'views/filters',
            ),
        ));
        $this->setDefaultResourceType('model');
    }
}

仅在test / bootstrap.php中运行应用程序而不运行前端控制器:

<?php
// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

require_once 'Zend/Loader/Autoloader.php';  

$config = array(
    APPLICATION_PATH . '/configs/application.ini'
);

// Create application, bootstrap, and run
$application = new Zend_Application(
    APPLICATION_ENV,
    array('config' => $config)
);

$application->bootstrap();

答案 2 :(得分:0)

由于传统的Autoloader不起作用,我试图手动执行任何Zend应用程序的操作。这是最后得出的bootstrap.php

<?php    
// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

require_once 'Zend/Loader/Autoloader.php';
require_once 'Zend/Loader/Autoloader/Resource.php';
$resources = new Zend_Loader_Autoloader_Resource(array(
  'namespace' => 'Application',
  'basePath'  => APPLICATION_PATH
));

$resources->addResourceType('form','forms','Form');
$resources->addResourceType('model','models','Model');
$resources->addResourceType('dbtable','models/DbTable','Model_DbTable');
$resources->addResourceType('mapper','models/Mappers','Model_Mapper');

逻辑通常是Zend应该自己解决的问题。事实上,它是在我在Windows上运行的本地开发机器上实现的。但是在ubuntu上我需要具体化。

知道为什么会很有趣。如果有人可以向我解释推理,那么我可能最终会给你正确答案;)