1

Class

<?php 

class api
{
    private $key;
    private $secret;

    public function __construct($key, $secret)
    {
        $this->key = $key;
        $this->secret = $secret;
    }
}

Test

public function test_api_keys_are_set_on_initialization()
{
    $this->assertNotEmpty($this->api->key);
    $this->assertNotEmpty($this->api->secret);
}

PHPunit won't let you test private variables, obviously. But how can I write a test that checks if the keys are set in the __construct()?

Gerben Jacobs
  • 4,515
  • 3
  • 34
  • 56
  • 1
    possible duplicate of [PHPUnit: Doing assertions on non-public variables](http://stackoverflow.com/questions/8928905/phpunit-doing-assertions-on-non-public-variables) – STLMikey Apr 11 '14 at 21:12

2 Answers2

2

The code you show actually does not make sense. The class you want to test offers no way to the outside world to get these private properties back, so currently there is no use case for that class at all in production code.

But I suppose that class really contains at least one method that does make an API call to somewhere, using these two bits of information. You would test that the strings passed into the constructor show up in this call, because it is irrelevant whether or not they were stored in private properties, they must be present in the API call.

And to test this, you enter the world of mocking. There should be an object inside your api class that does the actual communication. And this object will get a method call with these secret strings. You should configure a mock object that checks that these strings are correctly passed.

If you do, you can then refactor anything related to storing these strings. You can rename the variables, you can move them into other object - anything would be possible, with your test still staying green because they do NOT test the internal structures of your class, only the observable behaviour from the outside. The outside world only cares about that.

But if you really thing you must test private properties: Use Reflection to make them accessible inside your test. Or write a getter method to read them.

Sven
  • 69,403
  • 10
  • 107
  • 109
  • You could also add reflection to ensure internal private variables are set correctly, if you really wanted to test the private methods and variables. I use reflection to ensure the private internals of our API and the functions that access them do not change parameter order or values, without the tests also being updated. Provides some regression reassurance. – Steven Scott Apr 14 '14 at 15:59
  • Actually you do not want to test the internals. It should be a valid change to rename the private property from `key` to `hash` if somebody sees this as a better fitting name for the content that's being stored, and this rename should not break any tests, nor force the need to change the tests to now check for a different internal variable. I understand that less experienced developers try to look into the internals of their classes, and I think it is ok to make this step in order to get better. And there also might be code that cannot be tested otherwise. Still it should be avoided. – Sven Apr 14 '14 at 20:45
0

This is tough to answer concisely, but this user does it much better: https://stackoverflow.com/a/8929561/290293

Community
  • 1
  • 1
STLMikey
  • 1,210
  • 7
  • 19
  • Yes, I found that one already. And I understand you don't do it (it's private for a reason). But for my use case, how can I solve the problem? – Gerben Jacobs Apr 11 '14 at 22:46