jpa-unit
jpa-unit copied to clipboard
Database not cleaned up after test
When I run the following code I would expect that the database is always cleared after each test and so the results of test1()
and test2()
would be the same. However test2()
returns two elements instead of the expected 1.
@ExtendWith(JpaUnit.class)
class CleanupTest {
@PersistenceContext(unitName = "my-test-unit")
private EntityManager entityManager;
@BeforeEach
void setup() {
Test t1 = new Test();
t1.setName("Test1");
entityManager.persist(t1);
}
@Test
void test1() {
List list = entityManager.createQuery("select t from Test t").getResultList();
System.out.println(list.size()); // 1
}
@Test
void test2() {
List list = entityManager.createQuery("select t from Test t").getResultList();
System.out.println(list.size()); // 2
}
}
Is there anything that I'm missing here? I tried with several combinations of the @Cleanup
and @Transactional
annotations at class and method level, but the result was always the same.
I'll try to take a closer look at it in the next few days. It looks like the @Before*
methods are not properly handled.
which JPA provider and which DB are you using? I just did a copy&paste of your code above and with JPA 2.1 hibernate implementation with h2 I receive a "1" each time.
One additional thing: The transaction "closure" encloses the entire test, including the setup (@BeforeEach
in JUnit5 and @Before
in JUnit4) and tear down steps (@AfterEach
in JUnit5 and @After
in JUnit4). That means, the query result you see in a test setup, like yours, comes from the JPA cache and not from the DB itself. Same is true for @Cleanup
and other "closures" defined by jpa-unit in a sense that they all enclose all setup steps, the actual test method and the tear down steps. At least for regular JUnit tests.
I see a benefit of having a more fine grained control, which is not given yet. #33 addresses such functionality. To enable that means however a pretty huge refactoring of the existing code base, so I don't know, when it will be available.
OK, thanks for the explanation. I will then try to use the @InitialDatasets
annotation when I need to populate the database.
I'm stuck with an ancient Hibernate 4.2.11 and and JPA 2.0 but I'm planning to update soon™ to up-to-date versions. The DB I'm using is HSQLDB.
You can also use the TransactionSupport
class and do something like
Test t1 = new Test();
t1.setName("Test1");
newTransaction(manager).execute(() -> {
entityManager.persist(t1);
});
in your setup
method. It will suspend the transaction started by default and open and commit a new one for the lambda block. It may be worth to clean the entityManager on commit, so the chained method clearContextOnCommit(true)
can be handy.
Please try it say if it helps.
If I can find some time, I'll check the functionality with you "ancient" setup :)
Unfortunately, your suggestion didn't work either. I get the same result as before. clearContextOnCommit(true)
also doesn't make a difference.
is it possible for you to send me your test project for better analysis?