Использование двунаправленных ассоциаций из доменных объектов в тестах @Transactional Junit - PullRequest
5 голосов
/ 12 июля 2011

У меня настроен тест @Transactional JUnit, и я хочу сохранить некоторые тестовые данные в базе данных, а также проверить правильность ассоциаций. Однако при тестировании ассоциаций они всегда оцениваются как нулевые, даже если это работает в нетранзакционном тесте.

Я сохраняю два объекта, используя аннотацию @Before:

@Before
public void testData() {
    TestObjectOne o = new TestObjectOne();
    o.setName("One");
    repo.saveEntity(o); //autowired

    TestObjectTwo t = new TestObjectTwo();
    t.setOne(o);
    t.setName("Two");
    repo.saveEntity(t);
}

При доступе к этим двум объектам в тесте я получаю правильные экземпляры:

    TestObjectOne o = repo.getOneByName("One");
    TestObjectOne t = repo.getTwoByName("Two");

При проверке связи между t и o я получаю правильную ссылку, потому что я явно определил эту связь:

    Assert.assertNotNull(t.getOne());

Но при проверке в обратном направлении объект o корректно не обновляется:

    Assert.assertNotNull(o.getTwos());

Ассоциация определяется в доменном объекте как

В One:

   @OneToMany(mappedBy = "one", fetch = FetchType.EAGER)
   private List<Two> twos;

В Two:

  @ManyToOne(optional = false)
  private One one;

Когда у меня тест не запускается как @Transactional, он, однако, работает хорошо.

edit сохранение сущностей внутри теста вместо метода @Before, не имеет значения.

Ответы [ 2 ]

4 голосов
/ 15 июля 2011

Вам необходимо очистить и очистить текущий сеанс после сохранения и перед загрузкой тестовых объектов для утверждений.

Когда вы сохраняете TestObjectOne o, его экземпляр сохраняется в сеансе Hibernate. Затем вы создаете TestObjectTwo t, добавляете ссылку на o и сохраняете ее, чтобы этот экземпляр теперь также оставался в сеансе Hibernate. Затем, когда вы вызываете get, Hibernate возвращает вам созданные ранее экземпляры, не обновляя их, чтобы отразить фактическое состояние. Поэтому перед загрузкой необходимо очистить и очистить сеанс - тогда кэш L1 сеанса будет пустым, а сущности будут загружены в основном.

public class MyTest {

    @Before
    public void setUp() {

        TestObjectOne o = new TestObjectOne();
        o.setName("One");
        repo.saveEntity(o); //autowired

        TestObjectTwo t = new TestObjectTwo();
        t.setOne(o);
        t.setName("Two");
        repo.saveEntity(t);

        /* push all changes to current transaction*/
        repo.getSessionFactory().getCurrentSession().flush();
        /* clean current session, so when loading objects they'll
           be created from sratch and will contain above changes */
        repo.getSessionFactory().getCurrentSession().clear();
    }

    @Test
    public void test() {
        TestObjectOne o = repo.getOneByName("One");
        TestObjectOne t = repo.getTwoByName("Two");

        Assert.assertNotNull(t.getOne());
        Assert.assertNotNull(o.getTwos());
    }
}
0 голосов
/ 13 июля 2011

Аннотация @Transactional запускает откат после теста, поэтому результаты не сохраняются в базе данных.

Для тестов, требующих сохранения данных, вы можете добавить аннотацию @Rollback(false) в дополнение к@Transactional один.

...