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.
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 theClientFactory
.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 extendMyCache
in the test class (without Mockito).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, andMyCache
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
Java Error: Cannot Make a Static Reference to the Non-Static Method
Difference Between Static and Final
How to Obtain the Start Time and End Time of a Day
Why Is This Java Code in Curly Braces ({}) Outside of a Method
How to Decode a String Encoded with Openssl Aes-128-Cbc Using Java
Handling Datetime Values 0000-00-00 00:00:00 in Jdbc
How to Disable the Default Console Handler, While Using the Java Logging API
String Replacement in Java, Similar to a Velocity Template
Maximum Amount of Memory Per Java Process on Windows
"Unmappable Character for Encoding Utf-8" Error
Guessing the Encoding of Text Represented as Byte[] in Java
Collections.Synchronizedlist and Synchronized
Chat Client Emoticons Window Java
Pass Array to Oracle Procedure
How to Decrypt an Encrypted Aes-256 String from Cryptojs Using Java