访问私有字段以进行junit测试

时间:2015-01-09 09:37:52

标签: java unit-testing reflection field

我正在尝试从类中初始化一个私有字段,以便对其方法进行单元测试。为此,我使用反射,但我总是得到一个IllegalArgumentException,我不明白我做错了什么。

我的代码看起来像这样:

public class MyClass {

  private BufferedReader reader;

  public void methodToTest(){
    doSomethingwith(reader);
  }

}

public class testClass{

@Test
public void testMethod(){
Field reader = MyClass.class.getDeclaredField("reader");
reader.setAccessible(true);
StringReader stringReader = new StringReader("some string");
BufferedReader readerToSet = new BufferedReader(stringReader);
reader.set(readerToSet, readerToSet);
MyClass instance = new MyClass();
instance.methodToTest();
}
}

我在尝试运行测试时遇到此错误:

Can not set java.io.BufferedReader field MyClass.receiveReader to java.io.BufferedReader

我也尝试从类中获取字段的值并设置为阅读器。但是该值返回null并且我仍然得到相同的错误消息。

我知道如何初始化该字段以便我可以测试该方法吗?

5 个答案:

答案 0 :(得分:3)

您必须在之前实例化对象,然后才能设置其字段! (而且你拼错了BufferedReader参考。)

Field reader = MyClass.class.getDeclaredField("reader");
reader.setAccessible(true);
MyClass mc = new MyClass();
StringReader stringReader = new StringReader("some string");
BufferedReader readerToSet = new BufferedReader(stringReader);
reader.set(mc, readerToSet);
mc.methodToTest();

答案 1 :(得分:3)

如果您正在使用spring,也可以使用spring-test。

import org.springframework.test.util.ReflectionTestUtils;

ReflectionTestUtils.setField(notificationService, "timeToLive", 90L);

答案 2 :(得分:2)

使用apache.commons.lang3

import org.apache.commons.lang3.reflect.FieldUtils;

FieldUtils.writeField(myObject, "anyProperty", 420/*any value*/, true);

FieldUtils.readField(myObject, "anyProperty", true);

答案 3 :(得分:1)

您可以为此使用Mockito(org.mockito.internal.util.reflection.Whitebox)

Whitebox.setInternalState(object, "fieldName", fieldValue);

答案 4 :(得分:0)

@kocko的回答在大多数情况下都是正确的。但是,如果您不想显示实施细节,则可以不在您的字段(default访问级别)中设置访问级别修饰符。

因此,在您的情况下,字段声明应如下所示:

public class MyClass {
    BufferedReader reader;
    ...
}

然后确保您的测试与您的代码位于同一个包中,但在test目录中。如果一切正确,您将能够在任何黑客攻击时访问它。

注意:default访问级别意味着该内容仅在类和包内可见。