Monday 10 July 2017

Test for private constructor to get full code coverage

Imagine we have a simple helper class which only consists of public static methods.
[code lang=“java“]
public class Helper {
public static void doSomething() {}
}[/code]
And the test:
[code lang=“java“]
import org.junit.Test;
public class HelperTest {
@Test
public void testDoSomething() throws Exception {
Helper.doSomething();
}
}
[/code]
Our code coverage tool won’t show us a 100% coverage, because the (default) constructor is not invoked. For example Intellij IDEA only shows 50%.
One solution would be to simply invoke the default constructor with new Helper.doSomething(). But we don’t want to have objects of this class and therefore override the default constructor with a private one:
[code lang=“java“]
public class Helper {
private Helper() {}
public static void doSomething() {}
}
[/code]
The problem is, that now even the test cannot instantiate the class. And as we are testdriven, the question is: Should the decision to create a class without any objects be motivated by tests, too? In my opinion yes. I don’t want some other programmer to remove the private constructor. At least a test shall break.
We reach this by the following test:
[code lang=“java“]
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import org.junit.Test;
public class HelperTest {
@Test
public void testDoSomething() throws Exception {
Helper.doSomething();
}
@Test
public void testPrivateConstructor() throws Exception {
Constructor constructor = Helper.class.getDeclaredConstructor();
assertTrue("Constructor is not private", Modifier.isPrivate(constructor.getModifiers()));
constructor.setAccessible(true);
constructor.newInstance();
}
}
[/code]
Now we have a guard to the design decision of a private constructor and our tests are back on 100% coverage again.

No comments:

Post a Comment