0
votes

I'm trying to test a function wich walks through a class, takes the public properties and makes an object with it. The non public properties are ignored in the output. So ,I mock the class that will be processed and add it some properties. This is my code :

class GetSettingsTest extends TestCase
    {
    public function getExpected() {
        return (object) [
            "one" => (object) [
                "oneOne" => "1.1",
                "oneTwo" => "1.2",
                "oneThree" => (object) [
                    "oneThreeOne" => "1.3.1",
                    "oneThreeTwo" => "1.3.2",
                ]
            ],
            "two" => (object) [
                "twoOne" => "2.1",
                "twoTwo" => "2.2",
                "twoThree" => (object) [
                    "twoThreeOne" => "1.3.1",
                    "twoThreeTwo" => "1.3.2",
                ]
            ],
            "three" => (object) [
                "threeOne" => "3.1",
                "threeTwo" => "3.2"
            ]
            // four is not here : it is protected or private.
        ];
    }

    public function getSettingsMock() {

        $stub = $this->getMockBuilder('FakeSettingsClass')
            ->disableOriginalConstructor()
            ->getMock();

        $stub->one = (array) [
            "oneOne" => "1.1",
            "oneTwo" => "1.2",
            "oneThree" => (array) [
                "oneThreeOne" => "1.3.1",
                "oneThreeTwo" => "1.3.2",
            ]
        ];
        $stub->two = (array) [// provide an array, must return an object
            "twoOne" => "2.1",
            "twoTwo" => "2.2",
            "twoThree" => (object) [// provide an object, must return an object
                "twoThreeOne" => "1.3.1",
                "twoThreeTwo" => "1.3.2",
            ]
        ];
        $stub->three = (array) [
            "threeOne" => "3.1",
            "threeTwo" => "3.2"
        ];
        $stub->four = (array) [
        // I want this to be protected or private to be not present in the output.
            "fourOne" => "4.1",
            "fourTwo" => "4.2"
        ];
        return $stub;
    }

    public function testGetSettings() {
        $expected = $this->getExpected();
        $getSettings = new GetSettings($this->getSettingsMock());
        $value = $getSettings->getSettings();
        $this->assertEquals($expected, $value);
    }
}

The function works well with a var_dump, it ignores non-public values as expected. The test works without the non-public part, but I want to test it with the non-public part. I can't figure how to test the non-public part in Phpunit. Probably by setting a protected value in the getSettingMock function but how can I do that?

1
I think the most painless solution is to create some fixture class (smth like Tests\Fixtures\SettingsGetter\ClassWithPrivates) and use its instance in your tests.xmike

1 Answers

0
votes

Here is a solution based on xmike's comment and with the Phpunit doc here : https://phpunit.readthedocs.io/en/9.0/fixtures.html.

make a fixture class like this :

class GetSettingsFixture
{

    public array $one = [
        "oneOne" => "1.1",
        "oneTwo" => "1.2",
        "oneThree" => [
            "oneThreeOne" => "1.3.1",
            "oneThreeTwo" => "1.3.2",
        ]
    ];

    public array $two = [
        "twoOne" => "2.1",
        "twoTwo" => "2.2",
        "twoThree" => [
            "twoThreeOne" => "1.3.1",
            "twoThreeTwo" => "1.3.2",
        ]
    ];

    public array $three = [
        "threeOne" => "3.1",
        "threeTwo" => "3.2"
    ];

    public string $four = "a string";

    private array $five = [ // this should be ignored in the output.
        "fiveOne" => "5.1",
        "fiveTwo" => "5.2"
    ];

    protected array $six = [ // this should be ignored in the output.
        "sixOne" => "6.1",
        "sixTwo" => "6.2"
    ];

    public function testFunction() { // this should be ignored in the output.
        return "something";
    }
}

And this test pass :

class GetSettingsTest extends TestCase
{
    private GetSettingsFixture $given;

    public function setUp(): void {
        // this function is executed before test.
        $this->given = new GetSettingsFixture(); // this call the fixture class.
    }

    public function tearDown(): void {
        // this function is executed after the test.
        unset($this->given);
    }

    public function getExpected() {
        return (object) [
            "one" => (object) [
                "oneOne" => "1.1",
                "oneTwo" => "1.2",
                "oneThree" => (object) [
                    "oneThreeOne" => "1.3.1",
                    "oneThreeTwo" => "1.3.2",
                ]
            ],
            "two" => (object) [
                "twoOne" => "2.1",
                "twoTwo" => "2.2",
                "twoThree" => (object) [
                    "twoThreeOne" => "1.3.1",
                    "twoThreeTwo" => "1.3.2",
                ]
            ],
            "three" => (object) [
                "threeOne" => "3.1",
                "threeTwo" => "3.2"
            ],
            "four" => "a string"
            // five, six are not here : it is protected or private.
            // testFunction is hot here too, it's not a property.
        ];
    }

    public function testGetSettings() {
        $expected = $this->getExpected();
        $getSettings = new GetSettings($this->given);
        $value = $getSettings->getSettings();
        $this->assertEquals($expected, $value);
    }

}