Static methods and variables in PHP are bad - they are a real pain in the test!

First of all, i was never a fan of static calls and variables as i always thought they cause problems. Using a lot of statics you might experience values leaking through different parts of application and you cant isolate functions (cron/testing/overrided environments). In general the encapsulation is gone and coupling explodes.

What i did not realize until this year, was the fact how difficult it is to create new unit tests for code filled with static calls and references. Its just impossible to deal with code that calls stuff like this:

self::myMethod();
ClassName::method();

What is even worse you might get direct access to static variables which looks like this:

self::$value;
ClassName::$value;

Using code like this its impossible to mock it in any way. Especially if you use it with a class name. Once we have late static binding coming with PHP 5.3 we might be able to deal with it by simply overriding the method in a mock class. Still im not sure it would work in 100% of our cases.

Any way, experience opened my eyes on how evil static calls really are :- )

Some tricks that work

You can mock static properties by injecting the desired value or object like this:

class SomeName {
    protected static $var;
}

class SomeNameMock {
    public function set_var($value){
        self::$var = $value;
    }
}

What you gain is way of setting the mock object or fixed value before the test.

There is still a problem though. Testing deeper call trees we might have functions accessing the mock value and expecting different values or calling different methods on shared static objects. Things get overly complicated easily and tests look like a bunch of magical mock invocations just to prepare the environment.

Its also very easy to loose control over this static garbage and end up with tests that work when ran separately. Then you run them all and some of them start failing. Some tests will have fixtures set incorrectly or wont clean after themselves and we are in trouble.

So my humble advice to everyone: use as little static class properties and static methods as possible.

If you really have to, try to at least make some accessor functions and call $this->accessor()->whatever but never ClassName::$var nor ClassName::method() etc.

Comments

Post new comment

Image CAPTCHA

About the author

Artur Ejsmont

Hi, my name is Artur Ejsmont,
welcome to my blog.

I am a passionate software engineer living in Sydney and working for Yahoo! Drop me a line or leave a comment.

Enjoy!