如何在Java中访问私有类成员?

Han*_*etz 4 java unit-testing jpa private mocking

我有数据模型类,包含私有字段,这些字段是只读的(通过getter函数).这些字段由我的JPA持久性提供程序(eclipselink)在正常操作期间使用数据库的内容设置.对于单元测试,我想将它们设置为来自持久层的模型的伪值.我怎样才能做到这一点?无论如何,eclipselink如何设置这些值?

简化示例:

@Entity
class MyEntity
{
    @Id
    private Integer _ix;

    public Integer ixGet()
    {
        return this._ix;
    }
}
Run Code Online (Sandbox Code Playgroud)

djn*_*jna 9

你可以嘲笑实体本身,提供你自己的getter实现吗?

您可以在模拟持久层中创建匿名扩展:

MyEntity x = new MyEntity() {
    public Integer ixGet() { return new Integer(88); }
};
Run Code Online (Sandbox Code Playgroud)

  • 请详细说明.在测试我编写的一些eclipse插件时,我已经非常广泛地使用了这种技术.除了温暖的幸福之外,没有注意到任何副作用. (2认同)

Jon*_*han 8

您需要使用Reflection API.使用Class.getField()来获取该字段,然后在该字段上调用setAccessable(true),以便您可以写入它,即使它是私有的,最后您可以在其上调用set()来写入新值.

例如:

public class A {
    private int i;
}
Run Code Online (Sandbox Code Playgroud)

您希望将字段"i"设置为3,即使它是私有的:

void forceSetInt(Object o, String fieldName, int value) {
    Class<?> clazz = o.getClass();
    Field field = clazz.getDeclaredField(fieldName);
    field.setAccessible(true);
    field.set(o, value);
}
Run Code Online (Sandbox Code Playgroud)

您需要处理许多例外情况.


frh*_*ack 5

您可以使用 Mockito 等测试库以读写模式访问对象内部状态。例如,使用 Mockito 时:

//read
Integer i = Whitebox.getInternalState(myEntity,"_ix")
//Write 
Whitebox.setInternalState(myEntity,"_ix", 123) 
Run Code Online (Sandbox Code Playgroud)