如果其中一个构造函数参数是 List 类型,是否可以使用 null 参数测试私有构造函数?
Is it possible to test a private constructor with a null parameter if one of the constructor arguments is type List?
我正在使用 jMockit 对一些新对象进行单元测试。在我的特殊情况下,我试图测试私有构造函数对空参数的反应。考虑这个例子:
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));
}
}
和
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;
}
}
如果我想用 jMockit 测试 Bar 构造函数,我可以使用 Deencapsulation.newInstance(Class classToInstantiate, Object...nonNullArgs)。但是,就我而言,我希望参数之一(特别是字符串之一)为空引用。在这种情况下,我必须使用方法 Deencapsulation.newInstance(Class classToInstantiate, Class[] parameterTypes, Object... initArgs)。这需要我传入 Class< List< String >>,但根据 this past answer,这是不好的做法,只能通过转换才能实现。
即使我真的把谨慎抛诸脑后,并尝试按照
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);
我收到错误
Caused by: java.lang.IllegalArgumentException: Specified constructor not found: DiscreteSlot(java.lang.String, java.lang.String, java.util.ArrayList)
有没有办法做我正在尝试的事情?
构造函数参数类型是List
,不是ArrayList
。只需这样做:
Deencapsulation.newInstance(
Bar.class,
new Class<?>[] {String.class, String.class, List.class}, // use List class literal
someString,
null,
someListOfStrings);
表达式new ArrayList<String>().getClass()
returnsArrayList.class
不等于List.class
.
您尝试调用的构造函数将 List
作为第三个参数,因此您应该将 List.class
作为数组中的第三个 class 传递,以便以反射方式调用它.
但是,您传递的是这个表达式的结果:
((Class<List<String>>)new ArrayList<String>().getClass());
等于
ArrayList.class
因为没有采用 ArrayList
的构造函数,它说找不到构造函数。
改为传递 List.class
。
我正在使用 jMockit 对一些新对象进行单元测试。在我的特殊情况下,我试图测试私有构造函数对空参数的反应。考虑这个例子:
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));
}
}
和
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;
}
}
如果我想用 jMockit 测试 Bar 构造函数,我可以使用 Deencapsulation.newInstance(Class classToInstantiate, Object...nonNullArgs)。但是,就我而言,我希望参数之一(特别是字符串之一)为空引用。在这种情况下,我必须使用方法 Deencapsulation.newInstance(Class classToInstantiate, Class[] parameterTypes, Object... initArgs)。这需要我传入 Class< List< String >>,但根据 this past answer,这是不好的做法,只能通过转换才能实现。
即使我真的把谨慎抛诸脑后,并尝试按照
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);
我收到错误
Caused by: java.lang.IllegalArgumentException: Specified constructor not found: DiscreteSlot(java.lang.String, java.lang.String, java.util.ArrayList)
有没有办法做我正在尝试的事情?
构造函数参数类型是List
,不是ArrayList
。只需这样做:
Deencapsulation.newInstance(
Bar.class,
new Class<?>[] {String.class, String.class, List.class}, // use List class literal
someString,
null,
someListOfStrings);
表达式new ArrayList<String>().getClass()
returnsArrayList.class
不等于List.class
.
您尝试调用的构造函数将 List
作为第三个参数,因此您应该将 List.class
作为数组中的第三个 class 传递,以便以反射方式调用它.
但是,您传递的是这个表达式的结果:
((Class<List<String>>)new ArrayList<String>().getClass());
等于
ArrayList.class
因为没有采用 ArrayList
的构造函数,它说找不到构造函数。
改为传递 List.class
。