PHPUnit - 当 processIsolation 设置为 false 时无法重新声明 class

PHPUnit - Cannot redeclare class when processIsolation set to false

类似的问题已经被问过好几次了

PHPUnit 触发新的致命错误

Fatal error: Cannot redeclare class Validator in /some/path/to/Validator.php on line 6

ValidatorTest class

class ValidatorTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider data_provider_rules
    */
    public function test_factory($rules)
    {
        define('DIR_SEP', DIRECTORY_SEPARATOR);
        define('SYS_DIR', '.'.DIR_SEP.'..'.DIR_SEP.'classes'); //relative path here

        require SYS_DIR.DIR_SEP.'Validator.php';

        $validator = Validator::factory();

        return $validator;
    }
}

还有 Validator class

class Validator
{
    private static $validator = FALSE;

    public function __construct()
    {
    }

    public static function factory()
    {
        if (empty(self::$validator))
        {
            self::$validator = new Validator();
        }

        return self::$validator;
    }
}

classes 是微不足道的,没有任何自动加载或 include/require。我正在 运行 从仅包含 ValidatorTest.php 和配置文件 phpunit.xml(从 here 复制)的单独测试目录中进行测试。当

时,测试 运行 正常
processIsolation="true"

当使用 require_once 而不是 require 时,测试也有效。 所以我的问题是哪个(如果有的话)和为什么:我是否必须明确地将 processIsolation 属性设置为 true(因为默认值为 false),使用 require_once(感觉不是最佳解决方案)或重构代码(停止使用静态作用域、相对路径等)?

您必须在测试之前使用 PHPUnit 注释

 /**
  * @preserveGlobalState
  * @runTestsInSeparateProcesses
  */
 class ValidatorTest extends PHPUnit_Framework_TestCase
{
...
}

或者,您可以在特定测试之上使用@runInSeparateProcess 而不是@runTestsInSeparateProcesses。

您正在使用 dataProvider,因此我们假设 test_factory 方法被调用了不止一次。

在这个方法中你有一个 require 句子。这将在测试内部或外部产生您遇到的错误。

这和你写的一样:

require SYS_DIR.DIR_SEP.'Validator.php';
require SYS_DIR.DIR_SEP.'Validator.php';

该解决方案正在改进您设置测试的方式:

根据定义,测试的前 3 行应该只执行一次,因此将它们放入 setUpBeforeClass:

class ValidatorTest extends PHPUnit_Framework_TestCase
{
     public static function setUpBeforeClass()
     {
         define('DIR_SEP', DIRECTORY_SEPARATOR);
         define('SYS_DIR', '.'.DIR_SEP.'..'.DIR_SEP.'classes'); //relative path here
         require SYS_DIR.DIR_SEP.'Validator.php';
     }

    /**
     * @dataProvider data_provider_rules
     */
     public function test_factory($rules)
     {
        $validator = Validator::factory();
        return $validator;
    }
}

无论如何,IMO 使用 require_once 并检查常量是否已经定义在测试中是好的。