Springboot / Kotlin:测试注入另一个 @ConfigurationProperties 类的类的最佳实践

问题描述 投票:0回答:1

我有一个 Kotlin 项目。

我创建了一个

@ConfigurationProperties
类,我想知道单元测试的最佳实践。

以下是我的属性类:

@ConstructorBinding
@ConfigurationProperties(prefix = "myapp")
data class MyAppProperties(
    /**
     * Base path to be used by myapp. Default is '/search'.
     */
    val basePath: String = "/myapp"
)

我在控制器中注入 MyAppProperties:

@RestController
final class MyAppController(
    myAppProperties: MyAppProperties
) {

    ...

}

我想测试我的控制器:

@ExtendWith(MockitoExtension::class)
internal class MyAppControllerTest {

    @Mock
    lateinit var myAppProperties: MyAppProperties

    @InjectMocks
    lateinit var myAppController: MyAppController

    ...

}

但我有以下 Mockito 错误:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class com.myapp.MyAppProperties
Mockito cannot mock/spy because :
 - final class

解决此问题的最佳解决方案是什么:

    /src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: mock-maker-inline

这个解决方案看起来不错,因为我们没有修改现有代码,但它为整个项目和所有最终类的 Mockito 添加了行为。

  • 使我的属性类
    open
    open class MyAppProperties...

这个解决方案需要修改代码并使类可扩展,这可能不是一件好事?

  • 通过 Maven 配置打开所有 @ConfigurationProperties 类:
    <plugin>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-maven-plugin</artifactId>
        <configuration>
            <args>
                <arg>-Xjsr305=strict</arg>
                <arg>-Xjvm-default=enable</arg>
            </args>
            <compilerPlugins>
                <plugin>all-open</plugin>
            </compilerPlugins>
            <pluginOptions>
                <option>all-open:annotation=org.springframework.boot.context.properties.ConfigurationProperties</option>
            </pluginOptions>
        </configuration>
        ...
    </plugin>

这个解决方案不需要修改代码,而是将所有@ConfigurationProperties类制作成

open
,这可能不是一件好事?

  • 不要模拟属性类并在 MyAppControllerTest 中初始化它:
    @ExtendWith(MockitoExtension::class)
    internal class MyAppControllerTest {
    
        val myAppProperties: MyAppProperties = MyAppProperties("/mypath")
    
        ...
    }

这不允许我们根据测试给出具体的行为。

spring-boot unit-testing kotlin mockito configurationproperties
1个回答
0
投票

当您正在寻找纯粹的单元测试时,我建议您使用最后一种方法(初始化)。在不同的测试中以不同的方式初始化测试对象是完全正常的,这在您的情况下意味着插入不同的配置。如果您愿意,您可以使用

@Nested
来统一它们。模拟数据类看起来太多了,因为您实际上是在模拟吸气剂。您也不会模拟存储库返回的普通实体。您的代码不会再长(可能会更短)并且(虽然在我们谈论微秒时并不明显)更快一点。

另一个考虑因素:控制器基本上是到服务层的简单传递,它们通常只包含在测试的集成测试中。对于您的特定测试,这将需要传递不同的配置。这会影响您的整体测试速度,尽管对于新配置,必须初始化新的 spring 上下文。

© www.soinside.com 2019 - 2024. All rights reserved.