我在内存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?
答案 0 :(得分:2)
我发现这更实用。我不是一次获取所有结果,而是根据标准获取结果并断言它们不是空的。
public void should_insert_correctly() {
Inserter out = new Inserter(session); // out: object under test
out.insert();
Criteria criteria;
criteria = getCriteria(session, 0);
assertNotNull(criteria.uniqueResult());
criteria = getCriteria(session, 1);
assertNotNull(criteria.uniqueResult());
}
private Criteria getCriteria(Session session, int i) {
Criteria criteria = session.createCriteria(MyEntity.class);
criteria.add(Restrictions.eq("x", expectedX[i]));
criteria.add(Restrictions.eq("y", expectedY[i]));
return criteria;
}
答案 1 :(得分:0)
有状态实体不应该覆盖equals - 也就是说,实体应该通过引用标识进行相等性比较 - 因此List.contains将无法正常工作。
我所做的是使用反射来比较原始实体和重新加载的实体的字段。遍历对象字段的函数忽略瞬态字段和注释为@Transient的字段。
我发现我不需要忽略id。当对象首次刷新到数据库时,Hibernate会为其分配一个id。重新加载时,该对象将具有相同的ID。
测试中的缺陷是您没有设置事务边界。您需要在一个事务中保存对象。当您提交该事务时,Hibernate会将对象刷新到数据库并分配其ID。然后在另一个事务中从数据库中加载实体。您将获得另一组具有相同ID和持久(即非瞬态)状态的对象。
答案 2 :(得分:-1)
我会尝试在Object.equals(Object)
课程中实施MyEntity
方法。
List.contains(Object)
使用Object.equals(Object)
(来源:Java 6 API)来确定对象是否在此列表中。
方法session.createCriteria(MyEntity.class).list();
返回 new 实例的列表,其中包含您插入的值(希望如此)。
所以你需要比较这些值。这可以通过Object.equals(Object)
。
澄清编辑:
您可以忽略equals
方法中的ID,以便比较仅关注“实际值”。
YAE(又一编辑):
我建议您阅读有关equals()
方法的文章:Angelika Langer: Secrets Of Equal。它很好地解释了所有背景信息。