Zend Framework 2从单元测试中删除硬编码路径

时间:2013-06-02 00:23:53

标签: phpunit zend-framework2

我正在阅读Zend Framework 2单元测试教程。在设置单元测试的过程中,他们在setUp方法中将应用程序配置的硬编码路径插入:

namespace AlbumTest\Controller;

use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;

class AlbumControllerTest extends AbstractHttpControllerTestCase
{
    public function setUp()
    {
        $this->setApplicationConfig(
            include '/var/www/zf2-tutorial/config/application.config.php'
        );
        parent::setUp();
    }
}

我无法相信这实际上已经完成并用作示例。

问题是,如何在单元测试setUp方法中获取应用程序配置而不对其进行硬编码?

更新

我对此的另一个相关问题是,为什么“模块”的单元测试需要访问应用程序配置?是否应该将模块隔离到单个模块的“单元测试”?

更新2:

在摆弄了一段时间后,我发现了一个相关的问题。在创建Album模块的教程中,指出不是在Module.php getAutoloaderConfig方法中返回配置结构,而是使用Composer创建类映射。但是,执行此操作时,由于缺少部分配置,因此单元测试将无法运行。要解决这部分问题,您需要在模块基目录中创建一个autoload_classmap.php并在其中返回一个空数组。然后使用getAutoloaderConfig中概述的代码使测试工作。

我仍然没有找到硬编码应用程序配置问题的解决方案,以及为什么实际上需要首先访问它。我正在测试一个模块,而不是一个应用程序。

3 个答案:

答案 0 :(得分:1)

我总是直接使用http://framework.zend.com/manual/2.3/en/tutorials/unittesting.html

中提供的功能
protected static function findParentPath($path)
{
    $dir = __DIR__;
    $previousDir = '.';
    while (!is_dir($dir . '/' . $path)) {
        $dir = dirname($dir);
        if ($previousDir === $dir) {
            return false;
        }
        $previousDir = $dir;
    }
    return $dir . '/' . $path;
}

将该函数放在ControllerTest类中,并在setUp函数中使用它,如下所示:

public function setUp()
{
    $modulePath = static::findParentPath("module");
    $this->setApplicationConfig(
        include $modulePath . '/../config/application.config.php'
    );
    parent::setUp();
}

答案 1 :(得分:1)

将应用程序配置路径硬编码放入$this->setApplicationConfig()方法,如Zend 2 Official Doc 非常糟糕的代码

要解决此问题,您可以使用@slawoj的答案Bootstrap class into same Zend 2 Official Doc使用Bootstrap class into Zend 2 Official Doc中的findParentPath($path)方法来获取应用程序配置路径。

还有另一个答案,可能会更好:

使用Same They said into Zend 2 official Doc并添加静态成员保存应用程序配置数组何时使用它来启动服务管理器静态成员。

<强> bootstrap.php中

class Bootstrap
{
    /**
     * ServiceManger Static member
     * @var ServiceManager
     */
    private static $serviceManager;

    /**
     * Application Configuration static member
     * @var array
     */
    private static $applicationConfiguration;

    /**
     * Initialize Tests Bootstrap
     */
    public static function init()
    {
        static::initAutoloader();
        if (file_exists(static::findParentPath('code') . '/config/application.config.php')) {
            // include application configuration
            $configuration = require static::findParentPath('code') . '/config/application.config.php';
            // initialize application configuration static member
            static::$applicationConfiguration = $configuration;
            // initialize service manager static member
            $serviceManager = new ServiceManager(new ServiceManagerConfig());
            $serviceManager->setService('ApplicationConfig', $configuration);
            $serviceManager->get('ModuleManager')->loadModules();
            static::$serviceManager = $serviceManager;
        }
    }

    /**
     * Get Application Service Manager
     * @return ServiceManager
     */
    public static function getServiceManager()
    {
        return static::$serviceManager;
    }

    /**
     * Get Application Configuration
     * @return array
     */
    public static function getApplicationConfig()
    {
        return static::$applicationConfiguration;
    }

    /**
     * Get Full Path include given path with it's parent path
     * @param string $path path name which we want to get it's parent
     * @return string
     */
    public static function findParentPath($path)
    {
        $dir = __DIR__;
        $previousDir = ".";
        // loop on Directories Path until get parent path
        while (!is_dir($dir . '/' . $path)) {
            $dir = dirname($dir);
            if ($previousDir == $dir) {
                return false;
            }
            $previousDir = $dir;
        }
        return $dir . '/' . $path;
    }

   // ........
}

然后将应用程序配置静态成员用于$this->setApplicationConfig()方法。

您的AlbumControllerTest类

class AlbumControllerTest extends AbstractHttpControllerTestCase
{
    public function setUp()
    {
        $this->setApplicationConfig(
            Bootstrap::getApplicationConfig()
        );
        parent::setUp();
    }
}

最后的解释可能会解决您的第一个问题

  

如何在单元测试setUp方法中获取Application配置   没有硬编码它的路径?

另一方面:第二个问题

  

为什么实际上需要首先访问它。我正在测试一个   模块,而不是应用程序

正如它建议大多数测试用例类扩展AbstractHttpControllerTestCase类似AbstractControllerTestCase

  

我们在此扩展的AbstractHttpControllerTestCase课程对我们有所帮助   设置应用程序本身,有助于调度和其他   在请求期间发生的任务,以及提供方法   声明请求参数,响应标头,重定向等等

因此,您的测试用例类可以使用getApplicationServiceLocator()获取Zend\ServiceManager\ServiceManager实例或使用getRequest()获取http请求的Zend\Stdlib\RequestInterface实例或getResponse()到{{ 1}}对于Http响应,所有这些方法都使用内部Zend\Stdlib\ResponseInterface方法启动getApplication()对象使用您的应用程序配置然后您需要使用Zend\Mvc\ApplicationInterface方法进入$this->setApplicationConfig()方法你的测试用例类来设置你的应用程序配置。

我将所有方法作为示例给出了它们,分配到AbstractHttpControllerTestCase哪个{{3}}类扩展它。

答案 2 :(得分:0)

尝试:

include  dirname(dirname(dirname(dirname(dirname(__DIR__))))).'/config/application.config.php'