SpringBoot 单元测试实践——配置隔离篇
前言作为一个 Java 开发,我相信大家或多或少都写过单元测试,特别是 SpringBoot 项目,它的 test 组件提供了大量的功能来帮助我们高效的完成单元测试。 这个系列我会分几个部分,通过实际的单元测试中遇到的问题场景,来分享一下如何利用 SpringBootTest 来快速实现或解决对应的单元测试需求及问题。配置隔离我们在进行单元测试时,特别是在本机运行时,经常会有这样的场景:单元测试的配置中的部分特定项需要和正式的配置区分(正式的配置是指发布到服务器上的配置,不管是开发、测试还是生产环境),比较常见的比如端口、文件目录信息等等和环境相关的配置。这种情况我们一般怎么处理? 可能很多人都是把正式配置 copy 一份,然后把其中的特定项改为测试所需要的配置,用于单元测试,比如:java 复制代码 @ContextConfiguration("/test-config.properties")class ApplicationContextTests {// do something}
这样在大部分场景下确实可以,但是还是存在问题,比如项目使用了配置中心怎么办,程序会使用配置中心的配置;还有如果正式配置变更了,我都要同步的来修改 test-config.properties,非常麻烦。覆盖配置 @TestPropertySourceSpring 帮我们考虑到了这些情况,我们可以直接通过覆盖 PropertySource 来解决:java 复制代码/**
指定配置文件*/@ContextConfiguration@TestPropertySource("/test.properties")class PropertySourceTests {// do something}
/**
指定某个属性*/@ContextConfiguration@TestPropertySource(properties = "port=8808")class PropertySourceTests {// do something}
我们可以直接通过 @TestPropertySource 注解来指定配置文件或者只指定某个配置项,通过 @TestPropertySource 指定的配置在 SpringBoot 中的优先级比较高,会覆盖通过 @PropertySource 注入的属性。动态配置在进行配置隔离时,还有一种场景可能是我们在运行单元测试时,还不知道配置是什么,需要在运行时来决定的,比如本地运行单元测试和 CICD 运行时,配置可能并不一样;又或者你的配置是从另一个服务获取的,而不是写死的。那这时候我们该怎么处理?@DynamicPropertySource 我们可以通过 @DynamicPropertySource 配置来在运行时动态的注入配置:java 复制代码 @ContextConfigurationclass DynamicPropertySourceTests {
@DynamicPropertySource 注解可以标记在方法上,通过 DynamicPropertyRegistry 类来将配置动态的进行注入,这样我们就可以在运行时来决定我们的配置项了。
@DynamicPropertySource 的优先级是很高的,它的优先级比上面我们说到的 @TestPropertySource 以及操作系统环境变量、程序的 properties、@PropertySource 注入的属性都要高。
总结上面总结了几种通过不同方式来隔离正式配置与测试配置的方法,实际在一般的业务场景下,如果不是非常注重单元测试的质量,我们可能不一定应用得上。但是在合适的场景下,通过 SpringBoot 提供的对应的功能,我们可以更简单且优雅的实现对应的功能。
评论