我如何 "obtain transaction-synchronized Session for current thread" 在 Micronaut / Kotest / Hibernate 测试中

How do I "obtain transaction-synchronized Session for current thread" in a Micronaut / Kotest / Hibernate test

我正在尝试在每次测试后清理我的组件测试使用的数据库,以便下一次测试时该数据库为空。为此,我有如下内容:

@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 */
}

然而,当我 运行 这样做时,我得到以下错误:

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

我在其他帖子中看到提到使用 @Transaction 来修饰方法或从会话工厂获取实体管理器,但是使用这些时错误是相同的。

运行在我的测试的 init { ... } 子句中使用此代码没有问题(即测试代码所在的位置),并且它完全按预期工作。但是如果我 运行 它在 afterEach 它有一个问题。

任何人都可以就如何解决这个问题提供一些建议吗?

谢谢!

找到解决方案,首先将SessionFactory添加到构造函数中:

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

afterEach方法中有以下内容:

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

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

值得一提的是,您还可以在 class 正文中声明 seshem,以便它们可以通过所有方法访问