This is the third and final part of a series that we started under the title “What should be considered for unit-testing”. In this article, we will take a look at how we can test a method that is using another static method.
Probably you are saying. Oh yeah, I know this dude, and believe me, This is such a pain… and I have to say, that I completely feel the same! In my opinion, static methods are generally misunderstood. Let’s just avoid an unnecessary headache by describing why do I think this way and establish a simple rule:
We use almost all the time static keywordjust for the static class properties and we avoid defining static methods.
You ask me why? honestly, I would rather hear your reason for defining static methods!
Just for the sake of testing, anybody who ever tried to write a unit test for a method, which uses another static method within itself, knows that you can’t mock it! and that is bad! real bad!
I know, you fancy developers might say, no it’s not completely true, because you can use power mock or superpower mock or … but it’s more like you intentionally cut yourself just because you know a fancy doctor who can stitch it for you!
Anyway, I assume that I could make my point against writing static methods. Now let’s say we are in a situation where we have to use a static method in our class and don’t have the authority to change that. In this case, there are a couple of ways to get around it. My favorite one is the most simple yet powerful one. I would wrap that single static method into an interface and inject the interface into the target class. This way I can finally mock the interface in my unit test!
public class Sample { public String isPositive(int a, int b) { return Calculator.add(a, b) > 0 ? "positive" : "negative"; } public static class Calculator { public static int add(int a, int b) {return a + b;} } }
when you want to test the positive method functionality you may want to mock the static add method and by now you should know it is going to be a simple task. But here is a good workaround:
public class Sample { CalculatorWrapper calculatorService; public Sample(CalculatorWrapper calculatorService) { this.calculatorService = calculatorService; } public String isPositive(int a, int b) { return calculatorService.add(a, b) > 0 ? "positive" : "negative"; } class CalculatorWrapperImpl implements CalculatorWrapper { @Override public int add(int a, int b) {return Calculator.add(a, b);} } interface CalculatorWrapper { int add(int a, int b); } static class Calculator { public static int add(int a, int b) {return a + b;} } }
You can see, that to get around it we had to add lots of unnecessary code into the production code, which is definitely not a decent thing. That is another good reason why we should avoid writing static methods in the first place.