4

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

简化示例:

@Entity
class MyEntity
{
    @Id
    private Integer _ix;

    public Integer ixGet()
    {
        return this._ix;
    }
}
4

8 回答 8

9

你可以模拟实体本身,提供你自己的吸气剂实现吗?

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

MyEntity x = new MyEntity() {
    public Integer ixGet() { return new Integer(88); }
};
于 2009-08-20T13:28:59.220 回答
8

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

例如:

public class A {
    private int i;
}

您想将字段“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);
}

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

于 2009-08-20T13:34:53.830 回答
4

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

//read
Integer i = Whitebox.getInternalState(myEntity,"_ix")
//Write 
Whitebox.setInternalState(myEntity,"_ix", 123) 
于 2016-05-08T15:29:36.207 回答
3

您可以使用类似powermock的模拟框架来绕过封装。在 powermock 中,您将Whitebox.setInternalState(..)用于设置私有成员。

一种侵入性较小的方法是模拟 getter 方法。这是否可行将取决于其他取决于内部状态的因素,但如果足够,这是更清洁的解决方案。

于 2009-08-20T13:35:06.420 回答
2

另一种选择,如果你真的不想公开,是创建一个测试子类,并在那里提供公共访问。

你有几个选择:

  • 创建存根以替换您的实体(首先提取接口)
  • 使用反射
  • 添加公共设置器进行测试
  • 将测试保存在包中并使用默认范围

对于一堆有用的技术,看看 Michael Feather 的书,有效地使用遗留代码

于 2009-08-20T13:32:53.257 回答
2

您可以为只读变量添加带有参数的构造函数。不要忘记添加默认(零参数)构造函数。

@Entity
class MyEntity
{
    @Id
    private Integer _ix;

    public MyEntity(Integer ix) {
        _ix = ix;
    }

    public MyEntity() {
        /*
         * Default constructor
         */
    }

    public Integer ixGet()
    {
        return this._ix;
    }
}
于 2009-08-20T13:40:22.577 回答
2

我过去使用过的一些方法:

  • 使 _ix 受保护,创建一个子类,在其中实现 setter
  • 创建一个构造函数,将 _ix 的值作为参数
  • 使用反射
于 2009-08-20T13:30:13.680 回答
1

构造函数是我认为的最佳方式。如果该实体必须是只读的(根本不允许在生产代码中创建新实例),您可以创建具有包访问权限的构造函数并仅在测试中使用它。并且有可能即使您将默认构造函数设为私有或使用包访问,您的持久性提供程序仍然能够使用此类实体,但不确定 - 请查看 eclipselink 文档。

于 2009-08-20T14:49:13.930 回答