我遇到了关于在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();
任何帮助将不胜感激。
答案 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上我需要具体化。
知道为什么会很有趣。如果有人可以向我解释推理,那么我可能最终会给你正确答案;)