jpa-unit icon indicating copy to clipboard operation
jpa-unit copied to clipboard

Database not cleaned up after test

Open holyhoehle opened this issue 6 years ago • 8 comments

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.

holyhoehle avatar Jan 21 '19 15:01 holyhoehle

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.

dadrus avatar Jan 22 '19 14:01 dadrus

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.

dadrus avatar Jan 26 '19 12:01 dadrus

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.

dadrus avatar Jan 26 '19 13:01 dadrus

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.

holyhoehle avatar Jan 29 '19 16:01 holyhoehle

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 :)

dadrus avatar Jan 29 '19 19:01 dadrus

Unfortunately, your suggestion didn't work either. I get the same result as before. clearContextOnCommit(true) also doesn't make a difference.

holyhoehle avatar Jan 31 '19 15:01 holyhoehle

is it possible for you to send me your test project for better analysis?

dadrus avatar Jan 31 '19 20:01 dadrus

Sorry for the long delay, but here's a test project that reproduces the issue.

jpaunittest.zip

holyhoehle avatar Feb 11 '19 16:02 holyhoehle