How to Add Test Coverage to a Private Constructor

How to add test coverage to a private constructor?

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.

How to test a private constructor in Java application?

Using reflection, you can invoke a private constructor:

Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor

However, you can make even that not possible:

private Utils() {
throw new UnsupportedOperationException();
}

By throwing an exception in the constructor, you prevent all attempts.



I would make the class itself final too, just "because":

public final class Utils {
private Utils() {
throw new UnsupportedOperationException();
}
}

Coverage for private constructor junit/emma

The best way to test private methods is to use Reflection.

There are many ways, but I would simple do this;

@Test
public void testConstructorIsPrivate() throws Exception {
Constructor constructor = Product.class.getDeclaredConstructor();
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
constructor.setAccessible(true);
constructor.newInstance();
}

This will cover the constructor when running the coverage tool emma.

Testing a class with private constructor

You can do a lot of things, but I think that from testing perspective Singleton-pattern is not a good choice.

  1. If you are using Mockito, you should extract the ClientFactory.createClient() call into a package-public (default) function. Mockito can spy singletons: spy(MyCache.class), and you can change the behavior of the extracted function. So you replaced the ClientFactory.

  2. You can replace your private constructor with a package-public contructor, and also you need to extract function mentioned in the first solution. After these changes you can extend MyCache in the test class (without Mockito).

  3. You can extract the functionality of MyCache into a package-public class, which is not singleton (but can't call from outside). You can test it nicely, and MyCache will be only a singleton wrapper of the extracted class.

I think reflection is anti-pattern, but I know that the default access modifier (the empty string) is also ugly a little bit.

A few words about your singleton-pattern. This is not bad, if you have only one thread, but if you are in a multi-threaded environment, you need this codes:

// you need volatile, because of JVM thread caching
private static volatile MyCache instance;

private MyCache() {}

public static MyCache getInstance() {
if (instance == null) {
synchronize(MyCache.class) {
// yes, you need double check, because of threads
if (instance == null) {
instance = new MyCache();
}
}
}
return instance;
}

Writing JUnit test for a private constructor passing parameters

From a black box testing standpoint

This code can't be tested. You can't even instantiate it, so there's no realistic way to go about this. There's no sense in testing something that can't be used like this.

If you want to make it testable, then you have to expose a static method to create instances of it. If that's a singleton or a factory, that's up to you - it's not apparent just from what you're showing us, but at least this would allow you to test the construction of it without really worrying about the private constructor.

You'd also have to make accessors to get at the fields, but make them package-private.

Further, invocations such as new String(String) in this case aren't needed, and may only serve to confuse you. You're passing in a String, so you don't need to create a new one.

Lastly, from a testing standpoint, getRequired() is tough to test; unless it mutates the state of the instance (which, again, you need to use to verify anything), there's no point to test it. It'll only ever return "success".

public class Example {

private String str1 = null;
private String str2 = null;

public static void main(String[] args) {
Example e = new Example(args[0], args[1]);
String req = e.getRequired();
System.out.println(req);
}

private Example(String a, String b) {
str1 = new String(a);
str2 = new String(b);
}

String getStr1() {
return str1;
}

String getStr2() {
return str2;
}

private String getRequired() {
//code using str1 and str2 here
return "success";
}

public static Example getNewInstance(String a, String b) {
return new Example(a, b);
}
}

From a white box testing standpoint

You can only use reflection to get at the private constructor and the fields to verify that they are set.

@Test
public void testExample() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Constructor<Example> exampleConstructor = Example.class.getDeclaredConstructor(String.class, String.class);
exampleConstructor.setAccessible(true);
Example example = exampleConstructor.newInstance("foo", "bar");

// verify
Field str1 = example.getClass().getDeclaredField("str1");
Field str2 = example.getClass().getDeclaredField("str2");
str1.setAccessible(true);
str2.setAccessible(true);

assertThat("foo", equalTo(str1.get(example)));
assertThat("bar", equalTo(str2.get(example)));
}

How to include private contructor in Line Coverage?

Invoke it using reflection or just mockit.Deencapsulation.newInstance(). Write a test method like this

@Test
public void privateConstructorCoverage() throws Exception {
Deencapsulation.newInstance(TestFactory.class);
}

Deencapsulation javadoc

Provides utility methods that enable access to (ie "de-encapsulate") otherwise non-accessible fields, methods and constructors belonging to code under test.

How can I test a final class with private constructor?

Reflection is probably the way to go: How do I test a class that has private methods, fields or inner classes?

By the way, this is possibly a duplicate of the question in the link provided.

Alternatively, could you create a wrapper method that is protected which simply forwards all calls to the private method?

JaCoCo and missed coverage of private default constructor

This is not supported. The official documentation says:

Filters for Code where Test Execution is Questionable or Impossible by Design

  • Private, empty default constructors - assuming no calls to it
  • Plain getters and setters
  • Blocks that throw AssertionErrors - Entire block should be ignored if a condition (if !assertion throw new AssertionError)

see also : https://github.com/jacoco/jacoco/issues/298

Update: This was fixed in https://github.com/jacoco/jacoco/pull/529 and should be in 0.8.0.



Related Topics



Leave a reply



Submit