2

我有一个曾经运行良好的测试套件。它基于 FWOpenCartTest,它是 PHPUnit_Framework_TestCase 的一个大后代,实现了一个 MVC 框架(基于 OpenCart)。

今天我不得不向这样的后代添加一个实例化另一个类的调用,该类在内部分配一个 var 流,如下所示:

    // register a variable stream wrapper
    require_once( DIR_SYSTEM . 'library/variable_stream.php' );
    $ok = stream_wrapper_register("var", "VariableStream");
    if (!$ok) {
        trigger_error("Failed to register protocol for a variable stream");
        exit;
    }

从那以后,我无法运行任何测试,因为我不断收到 PHPUnit 转储,例如:

phpunit ControllerAccountWishListTest.php
PHP Warning:  stream_wrapper_register(): Protocol var:// is already defined. in /var/www/domain.tld/public_html/system/engine/factory.php on line 73
PHP Stack trace:
PHP   1. {main}() /usr/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP   3. PHPUnit_TextUI_Command->run() /usr/share/php/PHPUnit/TextUI/Command.php:129
PHP   4. PHPUnit_Runner_BaseTestRunner->getTest() /usr/share/php/PHPUnit/TextUI/Command.php:150
PHP   5. PHPUnit_Framework_TestSuite->__construct() /usr/share/php/PHPUnit/Runner/BaseTestRunner.php:142
PHP   6. PHPUnit_Framework_TestSuite->addTestMethod() /usr/share/php/PHPUnit/Framework/TestSuite.php:212
PHP   7. PHPUnit_Framework_TestSuite::createTest() /usr/share/php/PHPUnit/Framework/TestSuite.php:834
PHP   8. FWOpenCartTest->__construct() /usr/share/php/PHPUnit/Framework/TestSuite.php:473
PHP   9. Factory->__construct() /var/www/domain.tld/public_html/unittests/VisualPHPUnit/app/test/opencart/FW_OpenCartTest.php:41
PHP  10. stream_wrapper_register() /var/www/domain.tld/public_html/system/engine/factory.php:73
PHP Notice:  Failed to register protocol for a variable stream in /var/www/domain.tld/public_html/system/engine/factory.php on line 75
PHP Stack trace:
PHP   1. {main}() /usr/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP   3. PHPUnit_TextUI_Command->run() /usr/share/php/PHPUnit/TextUI/Command.php:129
PHP   4. PHPUnit_Runner_BaseTestRunner->getTest() /usr/share/php/PHPUnit/TextUI/Command.php:150
PHP   5. PHPUnit_Framework_TestSuite->__construct() /usr/share/php/PHPUnit/Runner/BaseTestRunner.php:142
PHP   6. PHPUnit_Framework_TestSuite->addTestMethod() /usr/share/php/PHPUnit/Framework/TestSuite.php:212
PHP   7. PHPUnit_Framework_TestSuite::createTest() /usr/share/php/PHPUnit/Framework/TestSuite.php:834
PHP   8. FWOpenCartTest->__construct() /usr/share/php/PHPUnit/Framework/TestSuite.php:473
PHP   9. Factory->__construct() /var/www/domain.tld/public_html/unittests/VisualPHPUnit/app/test/opencart/FW_OpenCartTest.php:41
PHP  10. trigger_error() /var/www/domain.tld/public_html/system/engine/factory.php:75

这是导致错误的小测试:

<?php

require_once('FW_OpenCartTest.php');

class ControllerAccountWishListTest extends FWOpenCartTest {
    public function testTheContentsOfALoggedInCustomersWishList() {
        $controller = $this->loadControllerByRoute("account/wishlist");

            $this->customerLogin('username@domain.tld','9a24b01674');
            $controller->index();

            $this->assertEquals(1, preg_match('/Your wish list is empty./', $this->getOutput()));
    }
}

?>

我要问的是:这是 PHPUnit 和测试用例类 FWOpenCartTest 之间的交互吗?

完成的应用程序可以工作,如果我不使用 PHPUnit 而只是创建一个包装器来实例化测试它也可以工作。

如果有交互,有没有办法隐藏 stream_wrapper_register() 以便 FWOpenCartTest 的构造函数不会发现它已经分配?

4

1 回答 1

1

这就是我如何解决这个问题的我自己的个人情况。这并不意味着对每个人都是一种方式

前提:我是怎么来的

这个问题是我安装了一个非常有用的OpenCart 测试套件的结果。我喜欢它,因为如果您必须对 OpenCart 进行大量定制,它确实有助于控制整个项目。事实上,在定制如此庞大的 MVC 框架时,很容易造成意想不到的副作用。这变得更加重要,因为 OpenCart 本身并不像 WordPress 或 Drupal 那样实现“对零售开发者友好”的扩展/插件钩子。因此大多数专业的 OpenCart 开发人员都会安装第三方扩展引擎,通常是 VQMod 和 OpenCart Override Engine。

如何使测试工作

一旦安装了测试套件,您将继承您自己的 OpenCart 安装自定义。就我而言,单元测试旨在应用于我自己的代码,因此我不需要 1:1 忠实的安装快照。在这方面我很幸运,因为 Override Engine 的工厂类根本不能很好地与 PHPUnit 配合使用。两者都想使用 var 流,这会产生严重的冲突:即使强制 PHPUnit 和 Override Engine 使用相同的流,它们中的一个也会调用不受支持的函数并导致 PHP 错误。

因此我所做的是

1) 将我的 Override Engine 修改后的 OpenCart 安装的根 index.php 恢复为原始分发文件。但是我保留了自己的自定义设置。

以下屏幕截图显示了我查看两个 index.php 文件之间的差异。左侧是我正在“恢复”到原始版本的新版本,右侧是当前安装的基于其工厂类的 Override Engine 版本。

编辑:遗憾的是,我没有“代表”可以放入图片,所以这里是链接

2) 使用 Override Engine 修改更改恢复的 index.php。就我而言,我用我自己的版本替换了默认的缓存实例化代码。基本上,您将手动从 Override Engine 目录中包含您的文件,并将它们实例化以代替默认类。

3)如果需要,您必须编写模拟对象/成员以让测试套件运行。

如何运行 OpenCart 与 PHPUnit 兼容代码的示例,旨在使用 Override Engine 运行。

阶段 1:在单元测试用例的 index.php 中找到覆盖引擎“转换后的”代码:

// Cache
$cache = $factory->newCache();
$registry->set('cache', $cache);

阶段 2:将单元测试用例的 index.php 语句恢复到原始 OpenCart 版本:

// Cache
$cache = new Cache();
$this->registry->set('cache', $cache);

第 3 阶段:手动应用您已覆盖的类和/或提供模拟对象

// Cache
// $cache = new Cache();
require_once (OVERRIDE_ENGINE_ROOT . 'mymods/system/library/cache.php');
$cache =  new MyMods_Custom_Cache();
$this->registry->set('cache', $cache);

这就像我能得到的解决方案一样接近。

于 2013-11-26T12:40:15.483 回答