Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are static methods untestable?

Why are static methods untestable? Kindly exemplify (in PHP if possible).

like image 485
Czar Pino Avatar asked Jul 21 '12 10:07

Czar Pino


People also ask

Why static methods are not inherited?

Another thing to note is that you cannot override a static method, you can have your sub class declare a static method with the same signature, but its behavior may be different than what you'd expect. This is probably the reason why it is not considered inherited.

Should static methods be unit tested?

Unit testing a static method is no different than unit testing a non-static method. Static methods are not untestable in themselves. A static method that holds no state or doesn't change state can be unit tested. As long as the method and its dependencies are idempotent, the method can be unit tested.

Why static methods are better?

They are faster — Static methods are slightly faster than instance methods because in instance methods, you are also working with an implicit this parameter. Eliminating that parameter gives a slight performance boost in most programming languages.

Are static methods an Antipattern?

On the other hand, static state, or static methods with associated static state, are utterly evil. That is an anti-pattern. It frequently helps to define a method as being non-stateful (and therefore a legitimate static method) if, and only if, it always returns equivalent output on equivalent inputs.


1 Answers

Static methods themselves aren't untestable, but if the object being tested calls a static method then a test cannot "get in between" and make it call a stub method instead. If the object being tested instead calls a regular method, the test can give it an alternative object with a stub implementation of that method.

In general, rigid dependencies are less testable while dependency injection (google it) makes code more testable.

For instance, let's say we have a static method getCurrentUser() that is used by the class we are testing, as follows

class PostModel {
    //...
    public function getRecentPosts() {
        return $this->database->from('posts')
                ->where(array('user' => UserModel::getCurrentUser()))
                ->limit(10);
    }
}

Now UserModel::getCurrentUser() cannot be replaced with a stub method. If we make it a regular method that we call through an object reference instead, we can pass in an alternative stub object in our test.

class PostModel {
    private $userModel;
    public function __construct($userModel) { 
        $this->userModel = $userModel;
    }
    //...
    public function getRecentPosts() {
        return $this->database->from('posts')
                ->where(array('user' => $this->userModel->getCurrentUser()))
                ->limit(10);
    }
}
like image 165
mpartel Avatar answered Oct 10 '22 00:10

mpartel