Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA - How to truncate tables between unit tests

I want to cleanup the database after every test case without rolling back the transaction. I have tried DBUnit's DatabaseOperation.DELETE_ALL, but it does not work if a deletion violates a foreign key constraint. I know that I can disable foreign key checks, but that would also disable the checks for the tests (which I want to prevent).

I'm using JUnit 4, JPA 2.0 (Eclipselink), and Derby's in-memory database. Any ideas?

Thanks, Theo

like image 705
Theo Avatar asked Oct 13 '10 16:10

Theo


4 Answers

Simple: Before each test, start a new transaction and after the test, roll it back. That will give you the same database that you had before.

Make sure the tests don't create new transactions; instead reuse the existing one.

like image 20
Aaron Digulla Avatar answered Nov 03 '22 20:11

Aaron Digulla


The simplest way to do this is probably using the nativeQuery jpa method.

@After
public void cleanup() {
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();
    em.createNativeQuery("truncate table person").executeUpdate();
    em.createNativeQuery("truncate table preferences").executeUpdate();
    em.getTransaction().commit();
}
like image 124
Chris Hinshaw Avatar answered Nov 03 '22 21:11

Chris Hinshaw


I am a bit confused as DBUnit will reinitialize the database to a known state before every test.

They also recommend as a best practice not to cleanup or otherwise change the data after the test.

So if it is cleanup you're after to prepare the db for the next test, I would not bother.

like image 2
Peter Tillemans Avatar answered Nov 03 '22 20:11

Peter Tillemans


Yes, in-transaction test would make your life much easier, but if transaction is your thing then you need to implement compensating transaction(s) during cleanup (in @After). It sounds laborious and it might be but if properly approached you may end up with a set of helper methods (in tests) that compensate (cleanup) data accumulated during @Before and tests (using JPA or straight JDBC - whatever makes sense).

For example, if you use JPA and call create methods on entities during tests you may utilize (using AOP if you fancy or just helper test methods like us) a pattern across all tests to:

  1. track ids of all entities that have been created during test
  2. accumulate them in order created
  3. replay entity deletes for these entities in reverse order in @After
like image 2
topchef Avatar answered Nov 03 '22 21:11

topchef