Instantiating a Class with private constructor using Java/Mockito/PowerMockito

user5192032 picture user5192032 · May 25, 2016 · Viewed 11.6k times · Source

I am writing a test case using JUnit and the method under test takes a final class with a private constructor as a parameter. Since I cannot instantiate it with the new keyword I tried using Mockito but found out that Mockito doesn't like final class. I went to use PowerMockito which seemed reasonable to me but PowerMockito.mockStatic(Field.class); is a void method and I need a reference of Field so that I can pass it as an argument while invoking the method.

I want to catch IllegalArgumentException but first I need to pass reference of Field as an argument

Method under test

public boolean accept(Field field) { 
    if( ignoreNulls ) {
        try {
            if( field.get( super.getObject() ) == null ) {
                return false;
            }
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
    }

    return super.accept(field); 
} 

JUnit test case

   @Test(expected=IllegalArgumentException.class)
    public void testAccept() throws Exception {
      DefaultToStringBuilder builder = new DefaultToStringBuilder(new Object());
      PowerMockito.mockStatic(Field.class);

      builder.accept(?);
}

I am not sure how should I be doing this.

Thanks in advance

Answer

user5192032 picture user5192032 · May 25, 2016

We can actually use Core Java to achieve this. Code below shows how to do it.

    private Field field;

    @Test(expected=IllegalArgumentException.class)
    public void testAccept() throws Exception {
      Class<?> clazz = Field.class;
      Constructor<?> [] constructors = clazz.getDeclaredConstructors();

      for(Constructor cons: constructors) {
          cons.setAccessible(true);
          field = (Field) cons.newInstance();
      }

      DefaultToStringBuilder builder = new DefaultToStringBuilder(new Object());
      builder.accept(field);

      assertNotNull(builder);
    }