I'm asking because I'm trying to use a mocking framework (Mockito) which does not allow you to mock static methods. Looking into it I've found quite a few blog posts saying that you should have as few static methods as possible, but I'm having difficulty wrapping my head around why. Specifically why methods that don't modify the global state and are basically helper methods. For instance I have a class called ApiCaller
that has several static methods. One of the static method's purpose is to execute an HTTP call, deal with any custom issues our server might have returned (ex. user not logged in) and return the response. To simplify, something like:
public class ApiCaller {
...
public static String makeHttpCall(Url url) {
// Performs logic to retrieve response and deal with custom server errors
...
return response;
}
}
To use this all I have to do is call ApiCaller.makeHttpCall(url)
Now I could easily make this a non static method like:
public class ApiCaller {
...
public String makeHttpCall(Url url) {
// Performs logic to retrieve response and deal with custom server errors
...
return response;
}
}
and then to use this method call new ApiCaller().makeHttpCall()
but this just seems like extra overhead. Can anyone explain why this is bad and if there is a better solution to making the methods non static (other than just removing the keyword) so that I can stub out these methods using the mocking framework?
Thanks!
Static methods are bad for testability.Since static methods belong to the class and not a particular instance, mocking them becomes difficult and dangerous. Overriding a static method is not that simple for some languages.
This really depends. If the values your helpers operate on are primitives, then static methods are a good choice, as Péter pointed out. If they are complex, then SOLID applies, more specifically the S, the I and the D.
in static method we cannot call normal functions that is non - static functions. The static method can not use non static data member or call non-static method directly. this and super cannot be used in static context. Access only static type data (static type instance variable).
Helper methods are often declared as public static so they can be invoked with the class name like Classname. method().
The problem with static methods is they're very hard to fake when they're not relevant to the system you're trying to test. Imagine this code:
public void systemUnderTest() {
Log.connectToDatabaseForAuditing();
doLogicYouWantToTest();
}
The connectToDatabaseForAuditing()
method is static. You don't care what this method does for the test you want to write. But, to test this code now you need an available database.
If it were not static the code would look like this:
private Logger log; //instantiate in a setter AKA dependency injection/inversion of control
public void systemUnderTest() {
log.connectToDatabaseForAuditing();
doLogicYouWantToTest();
}
And your test would be trivial to write without a database now:
@Before
public void setUp() {
YourClass yourClass = new YourClass();
yourClass.setLog(new NoOpLogger());
}
//.. your tests
Imagine trying to do that when the method is static. I can't really think of a way except for modifying the logger to have a static variable called inTestMode
that you set to true in the setUp()
to make sure it doesn't connect to a database.
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