Why are static methods untestable? Kindly exemplify (in PHP if possible).
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.
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.
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.
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.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With