views:

373

answers:

3

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?

A: 

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.

Nat
Note that expectedEntities' and the actual insereted entities' ids are different. Because I am not saving expectedEntities and I don't need to.
nimcap
Then ignore the IDs when reflecting on the persistent fields of the objects.
Nat
Why should stateful entities do not override equals? Don't know it.
furtelwart
A: 

I would try to implement Object.equals(Object) method in your MyEntity class.

List.contains(Object) uses Object.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.

furtelwart
I don't find ignoring ids in equals() a good solution. What happens if I need to compare ids too in the future
nimcap
You can just change the equals() method and integrate comparison of the ids. Then the tests, which you wrote today, will fail!
furtelwart
By the way: Why the downvote?
furtelwart
I did not downvote
nimcap
I didn't say that, I would like to ask the downvoter to say why he didn't like my answer.
furtelwart
+2  A: 

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.

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;
}
nimcap