如何在用 Kotlin 编写的 JUnit 5 测试类中注入 Spring bean?

Posted

技术标签:

【中文标题】如何在用 Kotlin 编写的 JUnit 5 测试类中注入 Spring bean?【英文标题】:How to inject a Spring bean in a JUnit 5 test class written in Kotlin? 【发布时间】:2019-06-04 12:32:51 【问题描述】:

我尝试使用 JUnit 5 和 Spring Boot 在 Kotlin 项目中测试某些内容,但我无法在我的测试类中注入 bean。

我尝试了很多不同的注解,但是注入神经元起作用了……

这是我的测试类:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest
@ExtendWith(SpringExtension::class)
class FooTest 

   @Autowired
   lateinit var repo: BarRepository

   @BeforeAll
   fun setup() 
   

   @Test
   fun testToto() 
   

使用这种注释组合,代码会引发以下异常: java.lang.NoClassDefFoundError:org/springframework/boot/context/properties/source/ConfigurationPropertySource。 而且我实际上无法找到这个异常来自哪里......我试图对这个异常进行一些研究,但我没有找到任何令人满意的东西......

【问题讨论】:

【参考方案1】:

我猜你的依赖项有错误。如果您从https://start.spring.io/#!language=kotlin 生成一个新的 Spring Boot Kotlin 项目,然后按如下方式自定义您的依赖项,它将按预期工作:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-reflect</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-stdlib-jdk8</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <artifactId>junit</artifactId>
                <groupId>junit</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

还请注意,您不需要指定 @ExtendWith(SpringExtension::class),因为自 Spring Boot 2.1 起,@SpringBootTest 已经使用此注解进行元注解。

【讨论】:

感谢您的回答,但我不会开始新项目。我会浪费太多时间。我刚刚用你谈到的依赖项清理了我的 pom.xml,但它不起作用。如果我删除“ExtendWith”注解,注入将不起作用,并且我有 UninitializedPropertyAccessException(基本上是 Kotlin NPE)...您还有其他建议吗? 感谢您的帮助,您最终将我引向了解决方案。【参考方案2】:

我终于找到了解决问题的方法。我的 Spring Boot 版本最初是“1.5.3”,所以我将 pom.xml 更改为“2.0.2”版本。现在我的测试运行良好,并且我的 bean 已按预期正确注入。这是我的 pom.xml 的修改部分:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.2.RELEASE</version>
    <relativePath/>
</parent>

修改版本后一切正常。 以下是使用 Junit 测试的有用依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <artifactId>junit</artifactId>
            <groupId>junit</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.3.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <scope>test</scope>
</dependency>

【讨论】:

以上是关于如何在用 Kotlin 编写的 JUnit 5 测试类中注入 Spring bean?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JUnit 5 在 Kotlin 中创建 TestContainers 基测试类

如何将 Gradle 中的原生 JUnit 5 支持与 Kotlin DSL 结合使用?

如何使用 SpringBoot2、JUnit5 和 Kotlin 将配置属性注入单元测试

Kotlin + SpringBootTest + Junit 5 + AutoConfigureMockMvc:测试通过时应该失败(似乎@BeforeEach没有生效)

Kotlin 1.5.10,Gradle 7.0.2_2 - 找不到方法 testCompile() group=org.junit.jupiter,name=junit-jupiter-api,ve

在用 Kotlin 编写的 Android 库的公共 API 中处理 R8 + JvmStatic Annotation + Lambda