Unit Testing Static Methods of the Java Standard Library

Photo by Kozjat on Unsplash

We’ve all been at a point where in we’re writing up test cases for our application and we encounter a static method from the java standard library being called. Everything goes downhill from there. Mockito would give you ambiguous error messages. Notice there is no reason shared as to why is it throwing a NullPointerException and this is at the time of mocking.

Prerequisites

This post does expect some familiarity with Unit testing using frameworks like Mockito . The code sample is in Java 8 and does require one to have an understanding about Functional Interfaces and Lambda functions in general. But it’s not something you would need in depth understanding of. If you’re not from a Java background, don’t worry the code is fairly straight forward and readable, so you would be able to follow along.

What about other frameworks?

That’s a fair question. What about PowerMock? While I was researching on the topic I came across the PowerMock git repo, which explicitly states:

Writing unit tests can be hard and sometimes good design has to be sacrificed for the sole purpose of testability.

It helps unit test these methods but I could never make my peace with using a whole framework for just a few usages here and there. If you’d rather use a framework instead, then there are a lot of frameworks and the most popular one is PowerMock.

The example

For the simplicity of the blog post, let’s assume you’re writing a method that gets a rootDirectory and a fileName. The method needs to return the contents of the file. Now if using Java you would use the java.nio.file.Files API to call a method called walk() to iterate through all files in the directory and then you would use the readAllBytes() method in the java.nio.file.Files to read the contents of the file. The overall code would look like

The problem is, the java.nio.file.Files.walk() method and java.nio.file.Files.readAllBytes() method are both static. This causes a problem in unit testing this code since, we would not be able to mock the responses of these methods.

Functional Interfaces to the rescue

What we can notice, is that we are using two methods walk() and readAllBytes() and we don’t quite need any other method which is a part of java.nio.file.Files class.

The intuition is to create two functional interfaces, FileReader (reads all files in a directory) and ContentReader (reads the content of a single file) each doing one part of the process. Now instead of using java.nio.file.Files class, we inject the two Functional Interfaces using Constructor Injection.

Below is the updated code.

Now you can simply use Mockito to mock the dependencies using the @Mock and then use Mockito fluent syntax to mock the behaviour.

when(mockedFReader.fetchFilesInDirectory(any())).thenReturn(sample);

Why Functional Interfaces and not a Util class?

The answer is code coverage. Considering you create a new class and wrap the Files class methods, you still would have to deal with code coverage issues. Although, to test out your FileOperator class, you can mock dependency, you still have zero coverage on your Util class. Is that a good practice or not? is opinion based.

Also, using functional interfaces make it easier to inject dependencies especially when using a Dependency Injection framework like Spring.

Conclusion

In this blog post we looked at how to make the code that uses java standard library static methods, more testable.

I do not recommend you make Functional Interfaces for all your static methods because you can always refactor your code to make it more unit testable but when it comes to the java standard library, things become out of our hands.

Like this article? Please consider following @iam_Carrot on Twitter. Maybe click the clap👏 button a few times to show your support ⬇⬇

A Tech Enthusiast, develops software at Amazon, made a computer print “Hello World” once; didn’t leave software since. Such an obedient fella that computer 🖥️