jeudi 2 juin 2016

Is it possible to test a private constructor with a null parameter if one of the constructor arguments is type List?

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?

Aucun commentaire:

Enregistrer un commentaire