Reputation: 3125
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
Upvotes: 16
Views: 26299
Reputation: 840
Not the correct answer to this question. But was the first result from google page so here is the answer for Hibernate users:
import jakarta.persistence.EntityManager;
import org.hibernate.Session;
Session session = entityManager.unwrap(Session.class);
session.getSessionFactory().getSchemaManager().truncateMappedObjects();
Just call it in beforeEach.
Upvotes: 1
Reputation: 9168
Option 1: You can disable foreign key checks before truncating tables, and enable them again after truncation. You will still have checks in tests in this way.
Option 2: H2 database destroys the in-memory database when the last connection closed. I guess Derby DB supports something similar, or you can switch to H2.
See also: I wrote a code to truncate tables before each test using Hibernate in a related question: https://stackoverflow.com/a/63747005/471214
Upvotes: 0
Reputation: 33
I delete the DB file after each run:
boolean deleted = Files.deleteIfExists(Paths.get("pathToDbFile"));
A little dirty but works for me. Regards
Upvotes: 0
Reputation: 655
Better late then never ... I just had the same problem and came around a pretty simple solution:
persistence.xml
<persistence-unit name="Mapping4" transaction-type="RESOURCE_LOCAL" >
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>...</class>
<class>...</class>
<properties>
...
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
...
</properties>
</persistence-unit>
unit-test:
...
@Before
public void setup() {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
entityManager = factory.createEntityManager();
}
@After
public void tearDown() {
entityManager.clear();
entityManager.close();
factory.close();
}
...
Upvotes: 0
Reputation: 7285
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();
}
Upvotes: 19
Reputation: 10762
My setup is quite similar: it's Derby (embedded) + OpenJPA 1.2.2 + DBUnit. Here's how I handle integration tests for my current task: in every @Before
method I run 3 scripts:
My database has only 12 tables and the test data set is not very big, either — about 50 records. Each script takes about 500 ms to run and I maintain them manually when tables are added or modified.
This approach is probably not recommended for testing big databases, and perhaps it cannot even be considered good practice for small ones; however, it has one important advantage over rolling back the transaction in the @After
method: you can actually detect what happens at commit (like persisting detached entities or optimistic lock exceptions).
Upvotes: 0
Reputation: 328830
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.
Upvotes: 6
Reputation: 19823
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:
@After
Upvotes: 2
Reputation: 35341
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.
Upvotes: 2