2009-06-03 2 views
1

Я запускаю тесты JUnit, используя в памяти HSQLDB. Предположим, у меня есть метод, который вставляет некоторые значения в БД, и я проверяю, правильно ли вставил эти значения. Обратите внимание, что порядок вставки не важен.Сравнение объектов при модульном тестировании с Hibernate

@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])); 
} 

Проблема в том, что я не могу сравнивать ожидаемые объекты с фактическими, так как ожидается, идентификационная и идентификатор фактического различны. Поскольку setId() из MyEntity является закрытым (чтобы явно не указывать идентификатор параметра), я не могу установить все идентификаторы сущностей в 0 и сравнить их.

Как сравнить два набора результатов независимо от их идентификаторов?

+0

Не могли бы вы предоставить дополнительную информацию о значениях, в которых содержится ваш класс MyEntity? Есть ли какой-либо член, который может дать вам первичный ключ? – guerda

ответ

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

Объект с сохранением состояния не должен переопределять равные - то есть, сущности должны сравниваться для равенства посредством ссылочного идентификатора - поэтому List.contains не будет работать так, как вы хотите.

Что я делаю, это использование отражения для сравнения полей исходных и перезагруженных объектов. Функция, которая перемещается по полям объектов, игнорирует переходные поля и те, которые аннотируются как @Transient.

Я не считаю, что мне нужно игнорировать идентификатор. Когда объект сначала сбрасывается в базу данных, Hibernate присваивает ему идентификатор. Когда он будет перезагружен, объект будет иметь тот же самый идентификатор.

Недостаток теста заключается в том, что вы не установили границы транзакций. Вам нужно сохранить объекты в одной транзакции. Когда вы совершаете транзакцию, Hibernate будет очищать объекты до базы данных и распределять их идентификаторы. Затем в другой транзакции загружаются объекты обратно из базы данных. Вы получите еще один набор объектов, которые должны иметь одинаковые идентификаторы и постоянное (т. Е. Непереходное) состояние.

+0

Обратите внимание, что ожидаемые идентификаторы событий и фактические идентификаторы вложенных объектов различаются.Потому что я не сохраняю ожидаемые события, и мне это не нужно. – nimcap

+0

Затем игнорируйте идентификаторы при отражении на постоянных полях объектов. – Nat

+0

Почему объекты с сохранением состояния не переопределяют равные? Не знаю. – guerda

-1

Я бы попытался реализовать метод Object.equals(Object) в вашем классе MyEntity.

List.contains(Object) использует Object.equals(Object) (источник: Java 6 API), чтобы определить, находится ли Объект в этом списке.

Метод session.createCriteria(MyEntity.class).list(); возвращает список новых экземпляров со значениями, которые вы вставили (надеюсь).
Итак, вам нужно сравнить значения. Это легко сделать с помощью реализации Object.equals(Object).

Разъяснение прав:
Вы можете игнорировать идентификаторы в методе equals, так что сравнение заботится только о «реальных ценностях».

Yae (Yet Another Edit):
Я рекомендую прочитать эту статью о equals() метода: Angelika Langer: Secrets Of Equal. Он очень хорошо объясняет всю справочную информацию.

+0

Я не считаю игнорирование идентификаторов в equals() хорошим решением. Что произойдет, если мне нужно сравнить идентификаторы тоже в будущем – nimcap

+0

Вы можете просто изменить метод equals() и интегрировать сравнение идентификаторов. Тогда тесты, которые вы написали сегодня, не сработают! – guerda

+0

Кстати: почему нисходящий? – guerda