Why are static methods untestable? Kindly exemplify (in PHP if possible).
问题:
回答1:
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);
}
}
回答2:
Static methods are testable: http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html (it's in php), but if you want to test the interactactions between classes (i.e. using mocks and fake objects) you will probably prefer not to use it. That being said phpunit 3.5 allows you to stub these.
You might also want to look at When do I use static variables/functions in php? or search for some information about when to use static methods.
I use static methods inside a class (ie marked private or protected) as they are faster in the language I work with.
回答3:
Well-defined Static
methods are perfectly testable. You see, the problem isn't with the method itself, it's with the method's dependencies. If the method and its dependencies (and the dependencies' dependencies) are idempotent, then there's no problem. Problems arise when your Static
methods are calling other methods that are, for example, dependant on a global
.