3

I'm trying to clean up a database used by my component tests after each one so it's blank for the next. To do this I've got something like the following:

@MicronautTest
class ExampleTest(
    private val entityManager: EntityManager
) : BehaviorSpec() {

    override fun afterEach(testCase: TestCase, result: TestResult) {
        entityManager.transaction.begin()
        entityManager.createQuery("delete from DeviceEntity").executeUpdate()
        ementityManagertransaction.commit()
        entityManager.clear()
    }
    
    /* test code */
}

However when I run this I get the following error:

Could not obtain transaction-synchronized Session for current thread
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    at io.micronaut.transaction.hibernate5.MicronautSessionContext.currentSession(MicronautSessionContext.java:100)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:479)
    at io.micronaut.configuration.hibernate.jpa.TransactionalSessionInterceptor.intercept(TransactionalSessionInterceptor.java:56)
    at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:82)
    at io.micronaut.configuration.hibernate.jpa.TransactionalSession$Intercepted.unwrap(Unknown Source)
    at uk.arqit.cloud.device.core.service.v1.services.component.example.ExampeTest.afterEach(IncrementRatchetSuccessTest.kt:56)
...

I've seen in other posts mentions of using @Transaction to decorate the method or getting an entity manager from the session factory but when using these the error is the same.

There's no issue with running this code in the init { ... } clause of my tests (i.e. where the test code is) and it works exactly as expected. But if I run it in afterEach it has an issue.

Can anyone offer some advice on how to resolve this?

Thanks!

MysteriousWaffle
  • 439
  • 1
  • 5
  • 16
  • I think the default value for `rollback` on the `@MicronautTest` is `true`. Are your test methods inserting data that is not being rolled back? – Jeff Scott Brown Mar 10 '21 at 16:09
  • They are seemingly. I tried to issue a rollback with liquibase (I'm using this for setup) but that doesn't affect it - apparently INSERT commands don't generate their own rollback information so it doesn't work. I'm using the entity manager to issue a 'delete from x' on the tables I need to clear which is doing the job – MysteriousWaffle Mar 12 '21 at 07:06
  • Are the modifications that are being made in the test methods happening the same transaction that is being started because `@MicronautTest` is present? – Jeff Scott Brown Mar 12 '21 at 14:03
  • They were, but I've since modfied it to work the way the solution works below. Even if I started a new transaction or tried to synchronise the existing one it threw an error so the easier option seemed to be to create my own instead of asking Micronaut to inject one for me. It's worth saying, my actual solution creates it at the start of the class so before/after/init all share it (this works fine). – MysteriousWaffle Mar 12 '21 at 15:03
  • "Even if I started a new transaction or tried to synchronise the existing one it threw an error..." - Interesting. You should be able to use the existing transaction. That is the reason we start it. It isn't clear from the code in the question why that is happening. – Jeff Scott Brown Mar 16 '21 at 16:26

1 Answers1

2

Found the solution, first add the SessionFactory to the constructor:

@MicronautTest
class ExampleTest(
    private val entityManager: EntityManager,
    private val sessionFactory: SessionFactory
) : BehaviorSpec() {
    
    afterEach(...) {
        ...
    }
}

In the afterEach method have the following:

    override fun afterEach(testCase: TestCase, result: TestResult) {
        val sesh = sessionFactory.openSession()
        val em = sesh.entityManagerFactory.createEntityManager()

        /* do whatever you want with 'em' */
    }

It's worth saying, you can also declare sesh and em in the class body so they're accessbile by all methods

MysteriousWaffle
  • 439
  • 1
  • 5
  • 16