0
votes

I'm testing a logic flow by mocking a class and testing for the function call.

function() setUp() 
{
    $this->shipping_method = $this->getMockBuilder(Wc_Trincargo_Shipping_Method::class)
                    ->getMock();

    $this->shipping_method->set_post_data([
        'woocommerce_wc-trinicargo-shipping_waybill_password' => 'xxx',
        'woocommerce_wc-trinicargo-shipping_waybill_username' => 'xxxx',
        'woocommerce_wc-trinicargo-shipping_waybill_customer_id' => uniqid(),
        'woocommerce_wc-trinicargo-shipping_waybill_pickupdays' => 2
    ]);
}

set_post_data is a public method that sets a protected property.

Later down I test to call a another method that needs to check the said protected property. I know they say you can't mock protected and private properties but if the properties are being set by public methods....shouldn't it work?

2
You should not know that the method sets protected properties at first place. This is kinda wrong. That's the internal implementation of the method and you should not be aware of it, when you test.Royal Bg
@RoyalBg not sure what you are trying to say here.KArneaud
I'm trying to say that you test methods against business specification, not against the knowledge of the code behind. This is wrong. Imagine you are testing a compiled library and do not know the internal behavior of the code, you only know how it behaves dictated by the business.Royal Bg
initially I was testing the logic of the said method however the test was failing due to the said property not being set which was not really part of the test if that makes any senseKArneaud
oh, this is completely different. Check if there is specialzed framework for testing woocommerce. They themselves have tests in the project - check how do they do it.Royal Bg

2 Answers

1
votes

If you really need to access a protected property within a test and you don't have a getter (nor should you create one purely for a test), you could use reflection.

<?php

class MyClass
{
    protected $myProperty;

    public function setMyProperty($value) 
    {
        $this->myProperty = $value;
    }
}


$a = new MyClass();
$a->setMyProperty('TestValue');

// echo $a->myProperty; Can't do this because it's protected.

$r = new ReflectionProperty('MyClass', 'myProperty');
$r->setAccessible(true);
$value = $r->getValue($a);

echo $value; // 'TestValue'
0
votes

It is irrelevant that the protected property was sat from a public method. The visibility belongs to the property regardless. If you need to check the value of the property afterwards, create a public getter for that property.

Note that it is useless to test simple getters and setters. You should test what the class does with the values of the properties instead.

Example of a useless test:

class MyClass {
    private $prop;
    public function setProp($value) {
        $this->prop = $value;
    }
    public function getProp() {
        return $this->prop;
    }
}

Test

$myClass = new MyClass();
$myClass->setProp('foo');
assertTrue($myClass->getProp() === 'foo');

Example of a class that uses a prop in a meaningful way, which determines the behavior/output of another method:

class MyClass2 {
    private $prop;
    public function setProp($value) {
        $this->prop = $value;
    }
    public function getPropUpperCase() {
        return strtoupper($this->prop);
    }
}

Test

$myClass2 = new MyClass();
$myClass2->setProp('foo');
assertTrue($myClass->getPropUpperCase() === 'FOO');