使用 Hibernate 进行单元测试时比较实体
我正在使用内存 HSQLDB 运行 JUnit 测试。 假设我有一个方法可以将一些值插入到数据库中,并且我正在检查该方法是否正确插入了这些值。 请注意,插入顺序并不重要。
@Test
public void should_insert_correctly() {
MyEntity[] expectedEntities = new MyEntity[2];
// init expected entities
Inserter out = new Inserter(session); // out: object under test
out.insert();
List list = session.createCriteria(MyEntity.class).list();
assertTrue(list.contains(expectedEntities[0]));
assertTrue(list.contains(expectedEntities[1]));
}
问题是我无法将预期实体与实际实体进行比较,因为预期的 id 和实际的 id 不同。 由于 MyEntity 的 setId() 是私有的(以防止显式设置 id),因此我无法将所有实体的 id 设置为 0 并进行比较。
如何比较两个结果集而不考虑它们的 id?
I am running JUnit tests using in memory HSQLDB. Let's say I have a method that inserts some values to the DB and I am checking if the method inserted the values correctly. Note that order of the insertion is not important.
@Test
public void should_insert_correctly() {
MyEntity[] expectedEntities = new MyEntity[2];
// init expected entities
Inserter out = new Inserter(session); // out: object under test
out.insert();
List list = session.createCriteria(MyEntity.class).list();
assertTrue(list.contains(expectedEntities[0]));
assertTrue(list.contains(expectedEntities[1]));
}
The problem is I cannot compare expected entities to actual ones because the expected's id and the actual's id are different. Since setId() of MyEntity is private (to prevent setting id explicitly), I cannot set all of the entities' id to 0 and compare like that.
How can I compare two result set regardless of their ids?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我发现这更实用。 我不是立即获取所有结果,而是根据标准获取结果并断言它们不为空。
I found this more practical. Instead of fetching all results at once, I am fetching results according to the criterias and asserting they are not null.
有状态实体不应该覆盖 equals —— 也就是说,应该通过引用标识来比较实体是否相等 —— 因此 List.contains 将无法按你想要的方式工作。
我所做的是使用反射来比较原始实体和重新加载实体的字段。 遍历对象字段的函数会忽略瞬态字段和注释为 @Transient 的字段。
我发现我不需要忽略 id。 当对象第一次刷新到数据库时,Hibernate 会为其分配一个 id。 重新加载时,该对象将具有相同的 id。
您测试中的缺陷是您没有设置事务边界。 您需要在一笔事务中保存对象。 当您提交该事务时,Hibernate 会将对象刷新到数据库并分配它们的 id。 然后在另一个事务中从数据库加载实体。 您将得到另一组应该具有相同 ID 和持久(即非瞬态)状态的对象。
A stateful entity should not override equals -- that is, entities should be compared for equality by reference identity -- so List.contains will not work as you want.
What I do is use reflection to compare the fields of the original and reloaded entities. The function that walks over the fields of the objects ignores transient fields and those annotated as @Transient.
I don't find I need to ignore the id. When the object is first flushed to the database, Hibernate allocates it an id. When it is reloaded, the object will have the same id.
The flaw in your test is that you have not set transaction boundaries. You need to save the objects in one transaction. When you commit that transaction, Hibernate will flush the objects to the database and allocate their ids. Then in another transaction load the entities back from the database. You will get another set of objects that should have the same ids and persistent (i.e. non-transient) state.
我会尝试在您的
MyEntity
类中实现Object.equals(Object)
方法。List.contains(Object)
使用Object.equals(Object)
(来源:Java 6 API) 来确定对象是否在此列表中。session.createCriteria(MyEntity.class).list();
方法返回一个新实例列表,其中包含您插入的值(希望如此)。所以你需要比较这些值。 这可以通过实现
Object.equals(Object)
轻松完成。澄清编辑:
您可以忽略
equals
方法中的 id,以便比较只关心“实际值”。YAE(另一个编辑):
我建议阅读这篇关于
equals()
方法的文章:安吉莉卡·兰格:平等的秘密。 它很好地解释了所有背景信息。I would try to implement
Object.equals(Object)
method in yourMyEntity
class.List.contains(Object)
usesObject.equals(Object)
(Source: Java 6 API) to determine if an Object is in this list.The method
session.createCriteria(MyEntity.class).list();
returns a list of new instances with the values you inserted (hopefully).So you need to compare the values. This is easily done via the implementation of
Object.equals(Object)
.Clarification edit:
You could ignore the ids in your
equals
method, so that the comparison only cares about "real values".YAE (Yet Another Edit):
I recommend reading this article about the
equals()
method: Angelika Langer: Secrets Of Equal. It explains all background information very well.