Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add test coverage to a private constructor?

People also ask

How do you mock a private constructor?

// Use the launcher of powermock @RunWith(PowerMockRunner. class) public class MyTestClass { @Test // Prepare the class for which we want to mock a static method @PrepareForTest(SiteUtil. class) public void myTest() throws Exception{ // Build the mock of Site Site mockSite = PowerMockito. mock(Site.

How do you write a test case for a constructor in Java?

To test that a constructor does its job (of making the class invariant true), you have to first use the constructor in creating a new object and then test that every field of the object has the correct value. Yes, you need need an assertEquals call for each field.

Can we have parameters in private constructor?

Using private constructor, prevents the creation of the instances of that class. If a class contains only private constructor without parameter, then it prevents the automatic generation of default constructor.

Can we use private modifier for constructor?

Modifiers public, protected and, private are allowed with constructors. We can use a private constructor in a Java while creating a singleton class.


I don't entirely agree with Jon Skeet. I think that if you can get an easy win to give you coverage and eliminate the noise in your coverage report, then you should do it. Either tell your coverage tool to ignore the constructor, or put the idealism aside and write the following test and be done with it:

@Test
public void testConstructorIsPrivate() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
  Constructor<Foo> constructor = Foo.class.getDeclaredConstructor();
  assertTrue(Modifier.isPrivate(constructor.getModifiers()));
  constructor.setAccessible(true);
  constructor.newInstance();
}

Well, there are ways you could potentially use reflection etc - but is it really worth it? This is a constructor which should never be called, right?

If there's an annotation or anything similar that you can add to the class to make Cobertura understand that it won't be called, do that: I don't think it's worth going through hoops to add coverage artificially.

EDIT: If there's no way of doing it, just live with the slightly reduced coverage. Remember that coverage is meant to be something which is useful to you - you should be in charge of the tool, not the other way round.


Although it's not necessarily for coverage, I created this method to verify that the utility class is well defined and do a bit of coverage as well.

/**
 * Verifies that a utility class is well defined.
 * 
 * @param clazz
 *            utility class to verify.
 */
public static void assertUtilityClassWellDefined(final Class<?> clazz)
        throws NoSuchMethodException, InvocationTargetException,
        InstantiationException, IllegalAccessException {
    Assert.assertTrue("class must be final",
            Modifier.isFinal(clazz.getModifiers()));
    Assert.assertEquals("There must be only one constructor", 1,
            clazz.getDeclaredConstructors().length);
    final Constructor<?> constructor = clazz.getDeclaredConstructor();
    if (constructor.isAccessible() || 
                !Modifier.isPrivate(constructor.getModifiers())) {
        Assert.fail("constructor is not private");
    }
    constructor.setAccessible(true);
    constructor.newInstance();
    constructor.setAccessible(false);
    for (final Method method : clazz.getMethods()) {
        if (!Modifier.isStatic(method.getModifiers())
                && method.getDeclaringClass().equals(clazz)) {
            Assert.fail("there exists a non-static method:" + method);
        }
    }
}

I have placed the full code and examples in https://github.com/trajano/maven-jee6/tree/master/maven-jee6-test


I had made private the constructor of my class of static utility functions, to satisfy CheckStyle. But like the original poster, I had Cobertura complaining about the test. At first I tried this approach, but this doesn't affect the coverage report because the constructor is never actually executed. So really all this tests is if the constructor is remaining private - and this is made redundant by the accessibility check in the subsequent test.

@Test(expected=IllegalAccessException.class)
public void testConstructorPrivate() throws Exception {
    MyUtilityClass.class.newInstance();
    fail("Utility class constructor should be private");
}

I went with Javid Jamae's suggestion and used reflection, but added assertions to catch anybody messing with the class being tested (and named the test to indicate High Levels Of Evil).

@Test
public void evilConstructorInaccessibilityTest() throws Exception {
    Constructor[] ctors = MyUtilityClass.class.getDeclaredConstructors();
    assertEquals("Utility class should only have one constructor",
            1, ctors.length);
    Constructor ctor = ctors[0];
    assertFalse("Utility class constructor should be inaccessible", 
            ctor.isAccessible());
    ctor.setAccessible(true); // obviously we'd never do this in production
    assertEquals("You'd expect the construct to return the expected type",
            MyUtilityClass.class, ctor.newInstance().getClass());
}

This is so overkill, but I gotta admit I like the warm fuzzy feeling of 100% method coverage.


With Java 8, it is possible to find other solution.

I assume that you simply want to create utility class with few public static methods. If you can use Java 8, then you can use interface instead.

package com.XXX;

public interface Foo {

  public static int bar() {
    return 1;
  }
}

There is no constructor and no complain from Cobertura. Now you need to test only the lines you really care about.