Java 访问junit测试的专用字段

Java 访问junit测试的专用字段,java,unit-testing,reflection,field,Java,Unit Testing,Reflection,Field,我试图从一个类初始化一个私有字段,以便对其方法进行单元测试。为此,我使用反射,但我总是得到一个非法的辩论例外,我不明白我做错了什么 我的代码如下所示: public class MyClass { private BufferedReader reader; public void methodToTest(){ doSomethingwith(reader); } } public class testClass { @Test

我试图从一个类初始化一个私有字段,以便对其方法进行单元测试。为此,我使用反射,但我总是得到一个非法的辩论例外,我不明白我做错了什么

我的代码如下所示:

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();
    }

}
public class MyClass {
    BufferedReader reader;
    ...
}
我在尝试运行测试时遇到此错误:

Can not set java.io.BufferedReader field MyClass.receiveReader to java.io.BufferedReader
我还尝试从类中获取字段的值并将其设置给读者。但是该值返回null,我仍然得到相同的错误消息


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

在设置字段之前,必须先实例化对象!(而且您拼错了BufferedReader引用。)


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

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

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();
    }

}
public class MyClass {
    BufferedReader reader;
    ...
}
然后确保您的测试与代码位于同一个包中,但位于
test
目录中。如果一切都做得好,你将能够访问它没有任何黑客


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

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


使用apache.commons.lang3

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

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

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

如果使用spring,也可以使用spring测试

import org.springframework.test.util.ReflectionTestUtils;

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

Whitebox在Mockito的
内部
包中,自
Mockito 2.6.2以来不再工作。您可以改用
org.mockito.internal.util.reflection.FieldSetter
,但这也在
internal
包中。Mockito似乎不希望您操纵私有字段,但在内部,这些方法与@kocko的解决方案相同