1

我正在使用内存 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 是什么?

4

3 回答 3

1

我发现这更实用。我不是一次获取所有结果,而是根据标准获取结果并断言它们不为空。

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;
}
于 2009-06-04T06:53:59.327 回答
0

有状态的实体不应覆盖 equals - 也就是说,应通过引用身份比较实体是否相等 - 因此 List.contains 不会按您的意愿工作。

我所做的是使用反射来比较原始实体和重新加载实体的字段。遍历对象字段的函数会忽略瞬态字段和注释为@Transient 的字段。

我发现我不需要忽略 id。当对象第一次刷新到数据库时,Hibernate 为其分配一个 id。重新加载时,对象将具有相同的 id。

您的测试中的缺陷是您没有设置事务边界。您需要在一个事务中保存对象。当您提交该事务时,Hibernate 会将对象刷新到数据库并分配它们的 ID。然后在另一个事务中从数据库中加载实体。您将获得另一组应具有相同 ID 和持久(即非瞬态)状态的对象。

于 2009-06-03T08:43:40.243 回答
-1

我会尝试Object.equals(Object)在您的课程中实现方法MyEntity

List.contains(Object)使用Object.equals(Object)(来源:Java 6 API)来确定对象是否在此列表中。

该方法session.createCriteria(MyEntity.class).list();返回一个包含您插入的值的新实例列表(希望如此)。
所以你需要比较这些值。这很容易通过Object.equals(Object).

澄清编辑:
您可以忽略equals方法中的 id,以便比较只关心“真实值”。

YAE(另一个编辑):
我推荐阅读这篇关于equals()方法的文章:Angelika Langer: Secrets Of Equal。它很好地解释了所有背景信息。

于 2009-06-03T09:04:54.583 回答