【问题标题】:Access static variable from "setUpBeforeClass" in "DataProvider" method in php unit test在php单元测试中的“DataProvider”方法中从“setUpBeforeClass”访问静态变量
【发布时间】:2019-03-22 21:08:53
【问题描述】:

我正在写我的phpunit test。我需要初始化一个dataprovider 方法来对我的一个测试进行分组。但我无法获得在setUpBeforeClass 方法中声明的静态变量。这些变量正在向我返回null

google 搜索时,文档说dataprovider 方法将在setUpBeforeClass 之前执行。

有什么方法可以覆盖它并从dataprovider 访问静态变量?

示例代码

setupbefore 类函数

public static function setUpBeforeClass()
{
    self::sampleVariable = 'Sample Data';
}

数据提供者功能

public function sampleDataProvider()
{
    echo self::sampleVariable;
}

【问题讨论】:

  • 您能分享一下这种需求的原因吗?看起来像一个有趣的用例..

标签: php php-7 php-7.1 phpunit


【解决方案1】:

PHPUnit 处理数据提供者方法的方式很奇怪。它们不是从运行测试的同一对象调用的,因此在调用 DP 的对象中,setupBeforeClass 将不会运行。 IMO 真是太愚蠢了,但我敢肯定,这样做是有原因的(xmike 解释了它in his answer 实际上。毕竟不是那么愚蠢 ;-)。

鉴于您的分配只是一个静态值(无论如何在您的示例中),您能否不简单地将其声明为类属性而不是通过setUpBeforeClass 设置它?我想情况可能会更复杂,因为您的示例表明阻止了这种方法:我只有您的示例可以作为我的建议的基础。

要做的另一件事是将setUpBeforeClass 中的逻辑抽象为一个单独的方法,并从sampleDataProvidersetUpBeforeClass 中调用该方法。

【讨论】:

    【解决方案2】:

    数据提供者与测试用例设置流程分离的原因是它们可以被定义为外部类方法。它也是关于将数据注入测试的。考虑这样的代码:

    class SampleTest extends PHPUnit_Framework_TestCase
    {
        public function __construct($name = null, array $data = array(), $dataName = '') {
            parent::__construct($name, $data, $dataName);
            var_dump('constructed');
        }
        public static function setUpBeforeClass() {
            parent::setUpBeforeClass();
            var_dump('beforeClass');
        }
    
        public function setUp(){
            var_dump('before');
        }
    
        /**
         * @dataProvider sampleDataProvider
         */
        public function testMethod($expected, $actual) {
            var_dump('test');
            $this->assertEquals($expected, $actual);
        }
    
        public function sampleDataProvider() {
            var_dump('dataProvider');
            return [
                [1, 1],
                [2, 2],
            ];
        }
    }
    

    运行它时,你会注意到首先构造了SampleTest 实例,然后调用了dataProvider,然后创建了SampleTest 的两个实例(一个测试方法乘以来自dataprovider 的两个数据集),然后运行beforeClass 方法,然后运行测试方法运行两次,注入来自提供者的数据集。

    目前尚不清楚您的特定用例是什么,但可能可以将上述案例重构为类似:

    class AnotherSampleTest extends PHPUnit_Framework_TestCase
    {
        public function testMethod() {
            foreach ($this->sampleDataProvider() as $dataSet) {
                list($expected, $actual) = $dataSet;
                $this->assertEquals($expected, $actual);
            }
        }
    
        public function sampleDataProvider() {
            return [
                [1, 1],
                [2, 2],
            ];
        }
    }
    

    这里sampleDataProvider 只是一个常规方法,所以你负责如何以及何时调用它,无论如何它会在setUpBeforeClasssetUp 之后被调用,所以它可以访问在那里设置或修改的任何东西,这样您就可以进行任何需要的调整。

    这种方法的缺点是您实际上无法将一种测试方法拆分为多个。因此,与每个只有几个断言的多个测试相比,这将是一个具有多个断言的测试。此外,您可能需要特别注意设置(我的意思是您可能需要在每次迭代之前刷新 smth) - 可以通过手动调用 setUp 来解决(乍一看)。

    不要认为如果没有关于您的特定用例的一些细节就可以提出任何进一步的建议。

    【讨论】:

    • > “数据提供者与测试用例设置流程分离的原因是它们可以定义为外部类方法”。啊,当然。尽管我什至在一些测试中这样做,但我并没有想到这一点。呃。为澄清干杯。
    【解决方案3】:

    尝试将变量 sampleVariable 声明为 静态的,然后检查。

    class MyClass
    {  
    private static $sampleVariable;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-03-17
      • 2015-07-22
      • 2012-06-29
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      • 1970-01-01
      • 2017-01-13
      • 2013-04-20
      相关资源
      最近更新 更多