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

PHPUnit-当processIsolation设置为false时,无法重新声明类,php,unit-testing,configuration,phpunit,Php,Unit Testing,Configuration,Phpunit,类似的问题在这里已经被问过好几次了 PHPUnit触发一个新的致命错误 致命错误:无法在第6行的/some/path/to/Validator.php中重新声明类验证器 验证程序测试类 class ValidatorTest extends PHPUnit_Framework_TestCase { /** * @dataProvider data_provider_rules */ public function test_factory($rules)

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

PHPUnit触发一个新的致命错误

致命错误:无法在第6行的/some/path/to/Validator.php中重新声明类验证器

验证程序测试

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;
    }
}
class Validator
{
    private static $validator = FALSE;

    public function __construct()
    {
    }

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

        return self::$validator;
    }
}
以及
验证程序

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;
    }
}
class Validator
{
    private static $validator = FALSE;

    public function __construct()
    {
    }

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

        return self::$validator;
    }
}
这些类很简单,没有自动加载或include/require。我正在从单独的tests目录运行测试,该目录只包含
ValidatorTest.php
和配置文件
phpunit.xml
(复制自)。测试在以下情况下运行正常:

processIsolation="true"

当使用一次
require\u
而不是
require
时,测试也会起作用所以我的问题是哪个(如果有的话)以及为什么:我是否必须显式地将
processIsolation
属性设置为
true
(因为默认值为false),使用
require\u一次(感觉不是最好的解决方案)或重构代码(停止使用静态范围、相对路径等)?

您必须在测试顶部使用PHPUnit注释

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

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

您使用的是
数据提供程序
,因此我们假设
测试工厂
方法被多次调用

在这种方法中,您有一个
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_一次
并检查常量是否已定义在测试中是可以的。

您能再解释一下为什么要这样做吗?有了这个注释,每个测试都将在自己的过程中开始。这可以防止类验证程序仍然存在,因为该类仅存在于另一个进程中。您不能在env for phpunit中使用自动加载系统,而不是使用
require
?@Matteo我没有使用自动加载(至少不是在php中)。我建议您尝试编写一个简单的autoload.php文件,然后再次启动测试类。PHPunit更喜欢在测试之外的自动加载。。。(要求等)。如果你喜欢,我可以试着给你写。让我知道require_Once()在执行过程中只会加载一次类,因此如果它们已经包含,则不会再次包含它们。每次访问类时,require都会加载这些类,这可能会导致重复声明。因此,如果我没有弄错的话,测试工厂的执行次数将与
数据提供程序中提供的数据相同?如果是这样,这似乎是一个合法的解决方案-setUpBeforeClass是缺少的一部分。您知道为什么带有
processIsolation
-IMHO的解决方案意味着“考虑提供的每个新数据,因为它将是一个对过去一无所知的新进程(本例中加载了哪些类)”。是的。使用数据提供程序时,对每个数据集执行一次测试。这很方便,因为你可以独立地获得关于哪些案例通过了哪些案例没有通过的信息。不确定你的问题是什么意思。进程隔离之所以有效,是因为作为不同的进程,以前没有加载其他类,但这是解决一个小问题的一种非常糟糕的方法。