【问题标题】:Spring Data MongoDB can't use @Transactional of my Repository Test: Failed to retrieve PlatformTransactionManager for @Transactional testSpring Data MongoDB 无法使用我的存储库测试的@Transactional:无法为@Transactional 测试检索 PlatformTransactionManager
【发布时间】:2021-02-25 07:47:21
【问题描述】:

我正在启动一个使用 Spring Data MongoDB 的简单 Spring Web 服务。我习惯于在 MySQL 中使用 Spring Data,这里在我的测试类中使用 @Transactional 效果很好。

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

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

现在这是我的测试课

@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>

我的任何应用程序类看起来像这样:

@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()
}

【问题讨论】:

    标签: spring-boot kotlin transactions spring-data-mongodb


    【解决方案1】:

    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);
    } 
    

    【讨论】:

    • 有没有办法通过应用程序,yaml?
    【解决方案2】:

    上面的 Kolin 版本是这样的:

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

    【讨论】:

      猜你喜欢
      • 2016-09-17
      • 1970-01-01
      • 2016-04-09
      • 2020-09-05
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      • 2013-08-25
      相关资源
      最近更新 更多