Spring Boot - 如何通过实现 BeforeAllCallback 的自定义扩展类设置或覆盖 application.yml 中定义的属性?

Posted

技术标签:

【中文标题】Spring Boot - 如何通过实现 BeforeAllCallback 的自定义扩展类设置或覆盖 application.yml 中定义的属性?【英文标题】:Spring Boot - How to set or override properties defined in application.yml via a custom extension class that implements BeforeAllCallback? 【发布时间】:2021-01-29 09:10:49 【问题描述】:

我有一个扩展类,它实现BeforeAllCallback 来设置这样的随机端口。

import org.junit.jupiter.api.extension.ExtensionContext
import java.net.ServerSocket

class CustomExtension : org.junit.jupiter.api.extension.BeforeAllCallback 
    var port: Int? = null

    override fun beforeAll(context: ExtensionContext?) 
        port = getRandomPort()
    
    
    private fun getRandomPort(): Int 
        ServerSocket(0).use  
            serverSocket -> return serverSocket.localPort 
        
    



另外,我在src/test/resources/application.yml 中定义了一个属性,就像这样。

app:
  random-port: 8765

这个属性被这个配置类使用。

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.ConstructorBinding

@ConstructorBinding
@ConfigurationProperties(prefix = "app")
data class PortProperty(
    val randomPort: Int
)

问题

CustomExtension 类运行我的测试时,如何覆盖硬线app.random-port?这个想法是为了让我的PortProperty 获得正确的值,而不是硬编码的值。

我的测试框架是JUnit5

import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
@ExtendWith(CustomExtension::class)
class RandomPortTest 

编辑

用例实际上是使用 AWS DynamoDBLocal 库为测试类启动本地 dynamo db。

【问题讨论】:

如果您只需要覆盖端口,我认为您不需要扩展。查看DynamicPropertySourceApplicationContextInitializer。例如:***.com/questions/31058489/…docs.spring.io/spring-framework/docs/current/… 这个用例实际上是使用 AWS DynamoDBLocal 库启动一个本地 dynamo db,这就是为什么我希望它成为一个扩展,这样我就可以对每个测试类做同样的事情。 【参考方案1】:

您可以在beforeAll 方法中设置app.random-port 系统属性。由于系统属性有higher priority 而不是属性文件,来自 application.yml 的端口值将被覆盖:

override fun beforeAll(context: ExtensionContext?) 
    port = getRandomPort()
    System.setProperty("app.random-port", port?.toString())

【讨论】:

以上是关于Spring Boot - 如何通过实现 BeforeAllCallback 的自定义扩展类设置或覆盖 application.yml 中定义的属性?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot如何配置SSL实现https协议

Spring Boot + OAuth2 + Google Login - 如何实现注销

如何在 Spring Boot 后端使用 jwt 令牌实现注销功能(使用休息端点)

spring boot事件如何使用

Spring(非boot)通过ssl发送邮件

Spring Boot核心原理实现及核心注解类