14

I have a class as following:

public class XConstants {

    public static final int A_TYPE = 1;
    public static final int B_TYPE = 2;
}

I am using both variables in my tests but when I examine the test coverage with Jacoco it shows %0 test coverage for this class. My guess is, it's because I never instantiate this class, just use its static variables. I tried creating an instance and test coverage went %100. How can I overcome this problem?

Murat Ayan
  • 575
  • 4
  • 19

4 Answers4

14

The JaCoCo measures test coverage based on percentage of bytecode which was actually executed. Declaring static final primitive or String constant creates no bytecode to execute, it's just an entry inside the constant pool. The only bytecode you have here is an implicit default constructor, usually like this:

aload_0
invokespecial Object.<init>
return

So when you don't call it, you have 0%, when you call it, you have 100%.

My suggestion is to ignore this problem. You shouldn't try to achieve 100% coverage no matter what. After all it doesn't guarantee anything: even 100% covered code may contain serious bugs.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
4

In our project we overcome problem of no coverage for class containing only constants by creating private constructor (following pattern from java.lang.Math):

private XConstants {}

and then using Trajano commons-testing library to assert that this constructor is private and invoke it to satisfy coverage:

assertUtilityClassWellDefined(XConstants.class)
Michal Kordas
  • 10,475
  • 7
  • 58
  • 103
4

You've made a class, which can be instantiated, but you never instantiated it, so technically you didn't cover that code. The simple solution for a "class full of constants" is to make it an interface instead. Also note that variables in an interface are public, static, and final by default, so your code can simply look like this:

public interface XConstants {
   int A_TYPE = 1;
   int B_TYPE = 2;
}
gwcoffey
  • 5,551
  • 1
  • 18
  • 20
3

[Updated] jacoco 0.8.0 has this by default configurated, for it to work you will need to add a private constructor.