I am using jMockit for unit testing of some new objects. In my particular case, I am attempting to test a private constructor's reaction to a null parameter. Consider the example:
public abstract class Foo {
private final String nickname;
public Foo(final String nickname) {
// Check condition
Preconditions.checkNotNull(nickname);
// Do some stuff
int i=0; while (i<10) {i++; System.out.println("I can count to "+i);}
// Store value
this.nickname = nickname;
}
public boolean isItMyName(String alias) {
return (nickname.equalsIgnoreCase(alias));
}
}
with
public class Bar extends Foo {
private final String professionalNickname;
private final List<String> jailhouseNicknames = new ArrayList<String>();
private Bar(final String casualNickname,
final String professionalNickname,
final List<String> jailhouseNicknames) {
super(casualNickname);
Preconditions.checkNotNull(professionalNickname);
Preconditions.checkNotNull(jailhouseNicknames);
this.professionalNickname = professionalNickname;
this.jailhouseNicknames.addAll(jailhouseNicknames);
}
@Override
public boolean isItMyName(String alias) {
if (super.isItMyName(alias)) return true;
if (professionalNickname.equalsIgnoreCase(alias)) return true;
for (String nick : jailhouseNicknames)
if (nick.equalsIgnoreCase(alias)) return true;
return false;
}
}
If I want to test the Bar constructor with jMockit, I can use Deencapsulation.newInstance(Class classToInstantiate, Object... nonNullArgs). In my case, however, I want one of the parameters (in particular, one of the Strings) to be a null reference. In that case, I must use the method Deencapsulation.newInstance(Class classToInstantiate, Class[] parameterTypes, Object... initArgs). This would require me to pass in Class< List< String > >, but according to this past answer, this is bad practice and is only possible through casting.
Even if I do throw caution to the wind and attempt something along the lines of
Class<List<String>> listClass = ((Class<List<String>>)new ArrayList<String>().getClass());
Deencapsulation.newInstance(
Bar.class,
new Class<?>[] {String.class, String.class, listClass},
someString,
null,
someListOfStrings);
I get the error
Caused by: java.lang.IllegalArgumentException: Specified constructor not found: DiscreteSlot(java.lang.String, java.lang.String, java.util.ArrayList)
Is there a way to do what I'm attempting?
The constructor you are trying to invoke takes a List
as the third parameter, so you should pass List.class
as the third class in the array in order to invoke it reflectively.
However, you are passing the result of this expression:
((Class<List<String>>)new ArrayList<String>().getClass());
which is equal to
ArrayList.class
Since there is no constructor which takes an ArrayList
, it says no constructor is found.
Pass List.class
instead.