I have a @Transactional JUnit Test set up and I want to persist some test data to the database and also test if the associations are correct. However, when testing the associations, they always evaluate to null, even though it does work in a non-transactional test.
I persist two objects using the @Before annotation:
@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);
}
When accessing those two objects in a test, I get the correct instances:
TestObjectOne o = repo.getOneByName("One");
TestObjectOne t = repo.getTwoByName("Two");
When checking on the association between t
and o
, I get a correct reference because I explicitly defined that association:
Assert.assertNotNull(t.getOne());
But when checking on the other way round, the object o
is not correctly updated:
Assert.assertNotNull(o.getTwos());
The association is defined in the domain object as
In One
:
@OneToMany(mappedBy = "one", fetch = FetchType.EAGER)
private List<Two> twos;
In Two
:
@ManyToOne(optional = false)
private One one;
When I have the test not run as @Transactional, it works nicely however.
edit saving the entities inside the test instead of the @Before method, doesn't make any difference.
You need to flush and clear the current session after saving and before loading test objects for assertions.
When You save the TestObjectOne o
the instance of it is kept in Hibernate session. Than You create TestObjectTwo t
and add reference to o
and save it so this instance is now also kept in Hibernate session. Than when You call get Hibernate gets You the instances You created earlier without updating them to reflect the actual state. So You need to flush and clear the session before loading - than the session L1 cache will be empty, and entities will be loaded corectly.
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());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With