Why is using static helper methods in Java bad?

北战南征 提交于 2019-11-28 23:08:07

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.

It is less modular. Instead you should define an interface ApiCaller with an instance method makeHttpCall() so that you can define separate implementations in the future.

In the very least you will always have 2 implementations of an interface, the original and the mocked version.

(Note: there are some mocking frameworks that allow you to mock static methods)

As an addendum, while this may not be the case in your specific application, typically the use of static methods is indicative of a larger design oversight. Designing for modularity and reuseability should be prevalent throughout your application, because even though you don't need it right now you may need it in the future, and it's much harder and much more time consuming to change things after the fact.

PRIVATE Static helper methods are not bad, in fact, they are actually preferred at the large corporation where I work. And I use Mockito with them all the time, accessed from the methods that call the static helper method.

There is a slight difference in how the compiler treats a static helper method. The byte code created will result in an invokestatic instruction, and if you remove the static the result will be one of the other instructions, like invokespecial. The difference there being that invokestatic loads the class to access the method, where invokespecial pops the object off the stack first. So there might be a slight performance advantage (maybe not).

That you can't mock them easily when you need to pretty much answers your own question.

Particularly when it's something as shown: making an HTTP call is expensive, and doing that for unit testing your code makes no sense–save that for integration testing.

Unit tests require known responses (and response codes) from HTTP calls, something that you can't do if you're calling someone else's service, using a network you don't control.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!