简体   繁体   中英

Access static variable from “setUpBeforeClass” in “DataProvider” method in php unit test

I am writing my phpunit test . I need to initialize a dataprovider method to group one of my test. But I am not able to get the static variables declared in the setUpBeforeClass method. Those variables are returning null to me.

When did a google search, the documentation said that the dataprovider methods will execute before setUpBeforeClass .

Is there any way to override this and make the static variable access from dataprovider ?

Sample code

setupbefore class function

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

dataprovider function

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

The reason for data providers to be decoupled from test case setup flow is that they can be defined as external class methods. Also it is about injecting data into tests. Consider such code:

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],
        ];
    }
}

when running it, you will notice that first SampleTest instance constructed, then dataProvider is invoked, then two instances of SampleTest created (one test method times two datasets from dataprovider), then beforeClass method runs, then test method is run twice having datasets from provider injected.

It is not quite clear what your particular use case is but is might be possible to refactor the case above into smth like:

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],
        ];
    }
}

here sampleDataProvider is just a regular method so you are in charge how and when to invoke it, and anyway it gets invoked after setUpBeforeClass and setUp so it has access to any stuff set up or modified there, so you can make any adjustments needed.

Downside of such approach is that you actually lose splitting one test method into multiple. So it will be one test with multiple asserts comparing to multiple tests with only a few asserts per each. Also you might need to take some extra care about setting up (I mean you might need to refresh smth before each iteration) - solvable by calling setUp manually (at first glance).

Don't think it is possible to make any further suggestions without some details on your particular use case.

try to declare the variable sampleVariable as static, and check.

class MyClass
{  
private static $sampleVariable;
}

The way PHPUnit handles data provider methods is weird. They're not called from the same object that the tests are run by, so in the object the DP call is made to, setupBeforeClass will not have been run. It's bloody daft IMO, but I'm sure there's a reason it's been done the way it has been done (xmike explains it in his answer actually. Not so daft after all ;-).

Given your assignment is just a static value (in yer example anyhow), can you not simply declare it as a class property instead of setting it via setUpBeforeClass ? I guess the situation might be more complicated that your example demonstrates that prevents this approach: I have only your example to base my suggestions on.

Another thing do do would be to abstract the logic from setUpBeforeClass into a separate method, and call that method from both sampleDataProvider , and setUpBeforeClass .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM