dstarh
dstarh

Reputation: 5076

Unit test passes when marked @Transactional but fails when not

Have a JUNIT test set up as such

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/applicationContext.xml", "/applicationContext-security.xml" })
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class BlahIntegrationTests{

 @Test
 public void testMappingsOfHugeObjectGraph(){
 }
}

I'm attempting to test that my hibernate mappings (annotation driven and JPA based) are correct and when run like above my test passes (just asserts that an ID is created).

If I take the @Transactional away, I get errors with some of my relationships which I was expecting. Anyone have thoughts on why it's not failing when it's @Transactional?

EDIT: To Clarify, the exception that was thrown was regarding bad hibernate mappings (it's a very large object structure and I had borked some of them) upon saving of the object

Upvotes: 2

Views: 2435

Answers (2)

František Hartman
František Hartman

Reputation: 15086

If you remove @Transactional your test DB won't be empty for another test and therefore tests won't be isolated.

If you have it there then some tests may pass even though they should fail (as you described, or another example is if you insert entity wich duplicates some unique constraint).

Solution is to have @Transactional in its place and inject

@PersistenceContext
private EntityManager em;

and do following before you extract your data from database

em.flush();
em.clear();

The first line will cause synchronization between session and database (your provider usually waits till the end of the transaction). The second line will remove all entities from session so all queries will go to the database.

And after the test everything is still rolled back so you have your database in original state.

Hope it helps.

Upvotes: 6

Affe
Affe

Reputation: 47974

If you take away @Transactional the Hibernate factory is running in its equivalent of auto-commit mode where each new access you make generates an entire new Session. So once you've retrieved an object it is immediately no longer associated with an open session and ineligible for Lazy Loading.

Upvotes: 0

Related Questions