简体   繁体   中英

Cannot access child property in parent class (calling method inherited from parent in child object)

So this is my parent class for unit testing (short version):

<?php
class TestCaseAbstract extends PHPUnit_Framework_TestCase
{
    protected $_rawPostData;

    public function setUp()
    {
        // ...
    }

    /**
     *
     * @dataProvider provider 
     */
    public function testFoo($rawData)
    {
        // ...
    }

    public function provider()
    {
        return array(
            array(''),
            array($this->_rawData),
        );
    }

    public function tearDown()
    {
        // ...
    }
}

This is my child class, an actual unit test case:

class FooTestCase extends TestCaseAbstract
{
    public function setUp()
    {
        $this->_rawPostData = '<?xml version="1.0"?><request><bogus /></request>';

        parent::setUp();
    }
}

Now when I run unit test case:

.phpunit --debug FooTestCase.php

I get this:

.
Starting test 'FooTestCase::testFoo with data set #0 ('')'.
.
Starting test 'FooTestCase::testFoo with data set #1 (NULL)'.
.

As you can see, the second unit test with data $this->_rawData says it ran with NULL data. What is wrong with my code? It seems the test method is not able to access protected property $this->_rawData.


I hope my inheritance model is not messed up. I have done a quick test just to make sure that the inheritance in PHP works as I think it works:

<?php

class ParentClass
{
    protected $_property;

    public function getProperty()
    {
        return $this->_property;
    }
}

class ChildClass extends ParentClass
{
    public function __construct()
    {
        $this->_property = 'Hello';
    }
}

$childClass = new ChildClass();
var_dump($childClass->getProperty());

This works and outputs "Hello" as it should. Any ideas why in my unit tests the data provider returns NULL?

This is caused by the way PHPUnit handles data provider methods. Each provider method is executed once with a new test case instance before any tests start. This is to allow it to get an accurate test count.

However, setUp() is not called before the data provider method. You can get around this by adding a method to return the desired data that the provider method can call. Define this new method as abstract in the base class and override it in the child. Also, don't forget to make your base class abstract.

abstract class TestCaseAbstract extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider 
     */
    public function testFoo($rawPostData)
    {
        // ...
    }

    public function provider()
    {
        return array(
            array(''),
            array($this->_getRawPostData()),
        );
    }

    protected abstract function _getRawPostData();
}

class FooTestCase extends TestCaseAbstract
{
    protected function _getRawPostData()
    {
        return '<?xml version="1.0"?><request><bogus /></request>';
    }
}

Update: I wrote a small test case to verify that PHPUnit doesn't call setUp() before data provider methods.

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