如果其中一个构造函数参数是 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