PHPUnit and abstract classes: how to test a concrete constructor that takes parameters and other concrete methods

I have a very simple class like this one below:

abstract class Person
{
    private $id;
    private $createdOn;

    // ... More private properties

    protected $unfound = array();

      

The constructor executes the foreach on the supplied $ data arrays and uses the correct methods to assign values ​​to the properties. If the method doesn't exist, then the key is added to the protected array to keep its trace (I called it $ unreasonable, just to be original!).

    public function __construct($data)
    {
        foreach ($data as $field => $value)
        {
            $method = 'set' . ucfirst($field);

            if (method_exists($this, $method))
            {
                $this->$method($value);
            }
            else
            {
                $this->unfound[] = $field;
            }
        }
    }

      

List of methods for setting property values

    public function setId($id) {
        $this->id = $id;
    }

    public function setCreatedOn($createdOn) {
        $this->createdOn = $createdOn;
    }

      

And a list of methods to get assigned values

    public function getId() {
        return $this->id;
    }

    public function getCreatedOn() {
        return $this->createdOn;
    }
} // END of the class

      

As you can see, the class doesn't do the hard task: it takes an array like

array(
    'id' => 4,
    'createdOn' => '2015-01-07 20:50:00',
    'unknownVar' => 'mah'
    // ... Other properties to set
    );

      

This way the class loops through the array and uses the key to call the correct method to set the value. I do not think anything difficult.

More difficult is testing instead.

Since it is an abstract class, I cannot create it directly, but I have to mock it.

My problem is that I cannot pass the correct parameters to the constructor in order to check if the values ​​are executed correctly.

I tried to use something like:

public function testPerson()
{
   $abstractClass = '\My\Namespace\Person';

    $testData = array(
        'id' => 1,
        'createdOn' => '2015-01-07 19:52:00',
        'unfound' => 'Inexistent method'
        );

   $methods = array(
      'getId',
      'setId'
      );

    $mock = $this->getMockBuilder($abstractClass)
        ->setConstructorArgs(array($testData))
        ->setMethods($methods)
        ->getMockForAbstractClass();

    $this->assertEquals($testData['id'], $mock->getId());
}

      

In testPerson (), the $ methods variable does not contain all the methods I need, but for testing the test (please excuse me for playing with words! :)) I think they are sufficient.

But PHPUnit tells me that:

Failed asserting that null matches expected 1.

      

The constructor doesn't seem to be called, also if the code coverage tells me the methods are being called.

is there anyone who can help me understand what is going on and how I can test this class?

Thank!

+3


source to share


1 answer


The solution is very simple: deleting the variable $methods

and calling it setMethods($methods)

solved the problem!

Calling setMethods()

, in fact, "stubs" those methods that, without setting the correct fixed value, are null (the value obtained from the test result).

The method I tested was stubbed while others were not.



So, a print_r($mock)

found that the other values ​​were set correctly.

So easy, but so hard to find! Thank you all the same for making me think, so I solved the problem and asked a question!

+2


source







All Articles