Spring 数据 MongoDB 无法使用我的存储库测试的 @Transactional:无法为 @Transactional 测试检索 PlatformTransactionManager

Spring Data MongoDB can't use @Transactional of my Repository Test: Failed to retrieve PlatformTransactionManager for @Transactional test

我正在启动一个使用 Spring 数据 MongoDB 的简单 spring Web 服务。我习惯于将 Spring 数据与 MySQL 一起使用,这里在我的测试中使用 @Transactional classes 工作正常。

但是在这种情况下,我收到以下错误消息:

Failed to retrieve PlatformTransactionManager for @Transactional test: [DefaultTestContext@39277750 testClass = ItemRepositoryTest, testInstance = com.ruckpack.equipmentservice.repository.ItemRepositoryTest@73bbbc73, testMethod = should test@ItemRepositoryTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@2c217989 testClass = ItemRepositoryTest, locations = '{}', classes = '{class com.ruckpack.equipmentservice.EquipmentServiceApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@15112c86, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@3400f6a3, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@39669485, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@dfa43ef, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@103a4d41, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@34fe2a08], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]
java.lang.IllegalStateException: Failed to retrieve PlatformTransactionManager for @Transactional test: [DefaultTestContext@39277750 testClass = ItemRepositoryTest, testInstance = com.ruckpack.equipmentservice.repository.ItemRepositoryTest@73bbbc73, testMethod = should test@ItemRepositoryTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@2c217989 testClass = ItemRepositoryTest, locations = '{}', classes = '{class com.ruckpack.equipmentservice.EquipmentServiceApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@15112c86, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@3400f6a3, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@39669485, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@dfa43ef, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@103a4d41, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@34fe2a08], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplication

现在这是我的测试class

@SpringBootTest
@Transactional
internal class ItemRepositoryTest @Autowired constructor(
    private val itemRepository: ItemRepository
) {
    @Test
    fun `should test`() {
        val expected = Item("001", "Meindl", "SuperBoot 300")
        itemRepository.save(expected)
        val actual = itemRepository.findById(expected.id)

        assertThat(actual).isPresent
        assertThat(actual.get()).isEqualTo(expected)
    }
}
@Repository
interface ItemRepository: MongoRepository<Item, String>

我的任何应用程序 class 如下所示:

@SpringBootApplication
class EquipmentServiceApplication

fun main(args: Array<String>) {
    runApplication<EquipmentServiceApplication>(*args)
}

我看到了这个教程:https://www.baeldung.com/spring-data-mongodb-transactions 在没有任何特殊配置的情况下完成了使用。这就是为什么我很困惑它不起作用的原因。

这是我的 build.gradle.kt 完整性

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.4.2"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    kotlin("jvm") version "1.4.30"
    kotlin("plugin.spring") version "1.4.30"
}

group = "com.ruckpack"
version = "0.0.1"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
    maven { url = uri("https://repo.spring.io/milestone") }
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("de.flapdoodle.embed:de.flapdoodle.embed.mongo")
    testImplementation("org.springframework.security:spring-security-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

MongoDB 版本 4 及以上支持事务。但在 Spring Data MongoDB 中默认禁用,您应该明确定义 MongoTransactionManager。 请阅读:https://docs.spring.io/spring-data/mongodb/docs/2.1.0.RC2/reference/html/#mongo.transactionshttps://www.baeldung.com/spring-data-mongodb-transactions 还说 “请注意,我们需要在我们的配置中注册 MongoTransactionManager 以启用本机 MongoDB 事务,因为它们在默认情况下处于禁用状态。”

不确定 Kotlin 中的语法,因为 Java 是:

@Bean
MongoTransactionManager txManager(MongoDbFactory mongoDbFactory) {
    return new MongoTransactionManager(mongoDbFactory);
} 

上面的 Kolin 版本类似于:

@Bean
fun txManager(mongoDbFactory: MongoDbFactory) : MongoTransactionManager = MongoTransactionManager(mongoDbFactory)