daGrevis
daGrevis

Reputation: 21333

How to test constructor that sets protected properties?

Well, I'm new to unit-testing (with phpUnit) and just started to test one class of mine.

Actual constructor looks like this:

/**
 * Loads configuration.
 */
function __construct() {

    $config =
        Kohana::$config->load('koffee');

    $this->_table_name = $config->table_name;
    $this->_table_columns = $config->table_columns;

}

It basically gets configuration from another file and sets it as protected properties to that object.

Here is how unit-test looks (it's not finished and that's where I need help):

/**
 * Tests that config is loaded and correct.
 */
function testConfigIsLoadedAndCorrect() {

    $object = new Model_Article();

    $config = Kohana::$config->load('koffee');

    // Compare object's **protected** properties to local `$config`. How?!

}

The problem is that properties are protected and I cannot access them so easy...

Possible solutions I see at the moment:

  1. Change visibility of properties (I don't like this),
  2. Add, so called, "getters" to class I test - not unit-test (I don't like this neither);

Probably this is funny to you, but, as I said, I'm new to unit-tests. Any help much appreciated.

Upvotes: 3

Views: 4556

Answers (4)

Adlaran
Adlaran

Reputation: 165

You can try to use ReflectionClass::newInstanceWithoutConstructor

$reflector = new ReflectionClass('Model_Article');
$object = $reflector->newInstanceWithoutConstructor();

Upvotes: 0

hakre
hakre

Reputation: 198119

Unit-testing is about unit testing. Protected members are not part of the public interface of a unit, which is all you should need to care about when writing unit tests.

You don't test the inner guts of a unit, but that it works as expected.

If you regardless of that want to do such stuff, you can use Serialization­Docs, casting to array and Reflection­Docs to inspect protected/private properties of an object or to execute protected/private methods of an object.


See as well: PhpUnit private method testingSO Q&A

Upvotes: 8

Trystan Spangler
Trystan Spangler

Reputation: 1769

You could create a subclass that does expose the data you need and only use it for unit testing.

You could also test the behavior of the class rather than the data. The Model_Article must do something with the table_name and table_columns so test that behavior. For example, if the Model_Article is used to create an html table, then you could set the config values, create the Model_Article, use it to create the html, then assert that it matches a hard coded string like <table title='name'><tr><th>col1</th><th>col2</th</tr></table>

[edit] You could also rely on constructor injection to pass the table_name and table_columns instead of having a hidden dependency on the configuration.

Upvotes: 2

Ahmish
Ahmish

Reputation: 1151

A technique I've used in the past has been to create a Tester class that exposes the appropriate methods to test the object. In this case, Model_Article_Tester would inherit Model_Article and expose a get method. The benefit here is you expose what you need for tests without affecting production code.

Upvotes: 2

Related Questions