我有一个裸Sping Boot 应用程序
@SpringBootApplication
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
它通过以下application.yml
连接到Spring云配置服务器
spring:
application:
name: client
config:
import: configserver:http://localhost:8888
当配置服务器运行时,应用程序工作正常,当服务器未运行时,应用程序按预期失败。
现在,我想用@SpringBootTest
为不依赖于正在运行的配置服务器,甚至不尝试连接到它的应用程序编写一个集成测试。
在配置服务器关闭的情况下,裸测试
@SpringBootTest
class ClientApplicationTests {
@Test
void contextLoads() {
}
}
失败,并显示预期的java.net.ConnectException: Connection refused
。
当我尝试使用禁用配置客户端时
@SpringBootTest(properties = "spring.cloud.config.enabled=false")
测试不尝试连接到服务器,但失败并显示
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
...
Caused by: java.lang.IllegalStateException: Unable to load config data from 'configserver:http://localhost:8888'
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:141)
...
Caused by: java.lang.IllegalStateException: File extension is not known to any PropertySourceLoader. If the location is meant to reference a directory, it must end in '/' or File.separator
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferencesForFile(StandardConfigDataLocationResolver.java:229)
问题是Sping Boot 2.4新引入的属性spring.config.import
的工作方式与所有其他属性不同,在我看来,只能向其添加值,而不能删除。
有没有办法在SpringBootTest
中覆盖spring.config.import
?有没有办法只抑制到配置服务器的连接?
5条答案
按热度按时间wgeznvg71#
在做了更多的研究之后,我发现了以下github问题:https://github.com/spring-cloud/spring-cloud-config/issues/1877
在我看来,如果需要在测试中覆盖
spring.config.import
,那么不令人满意的解决方案是从不将spring.config.import
放在application.yml
中。特别是对于配置服务器,它只应该放在一个特定于概要文件的配置文件中,或者放在一个多文档
application.yml
的特定于概要文件的文档中,然后您可以在生产中激活这个概要文件,而在测试和开发阶段保持它不活动。ff29svar2#
仅用于测试的溶液
通过这种方式,您可以在测试中将属性
configserver.import
设置为空字符串:现在为空的
spring.config.import
属性将不再被考虑。这什至可以在生产环境中使用-D
JVM启动参数覆盖。在测试场景中,这必须与
spring.cloud.config.enabled=false
配对,因为spring cloud config会检查至少一个以configserver:
前缀开头的spring.config.import
值,如果找不到匹配的属性,则不会让您启动。错误
原因是通过
spring.cloud.config.enabled=false
禁用Spring云配置,因为这也会删除其PropertySourceLoader bean,该bean处理所有以spring.config.import
为前缀的configserver:
。生产环境URL替换解决方案(还包括测试修复)
下面是另一个变体,它允许在生产环境中切换出配置服务器URL,因为多个
spring.config.import
定义不相互覆盖:为什么我们需要添加
spring.cloud.config.import-check.enabled
?因为spring cloud config要求在spring.config.import
中至少有一个configserver:
前缀值,但是在执行此检查之前不解析属性替换。因此spring cloud config只将${configserver.import}
视为字符串,并将阻止您的应用程序启动。spring.cloud.config.import-check.enabled = false
阻止上述检查。此外,环境变量CONFIG_SERVER_URL
可用于覆盖生产环境中的localhost configserver,同时如果configserver.import
在测试中设置为空,则仍允许spring.config.import
为空字符串。/rant:真是一场噩梦
g9icjywg3#
如果你除了测试之外到处都需要配置管理器,那么我认为解决你的问题的更好的方法是把
spring.config.import=configserver:http://localhost:8888
放在/scr/main/resources/application.properties
中,而不是把.yml
文件放在你项目的根目录中,然后你只需在测试中用spring.cloud.config.enabled=false
禁用它。另一个解决方案(如果你不想完全禁用它)是向该导入添加可选的关键字(
spring.config.import=optional:configserver:http://localhost:8888
)(这样你可以将其保留在.yml
中,但你将失去在测试中禁用它的能力,但它将简单地忽略服务器停机的事实。dzhpxtsq4#
我的解决方案是让Spring认为该位置已经使用自定义资源加载器加载。
此类在匹配前缀为
configserver:
的导入时将返回可选资源要工作,我们需要使用
spring.factories
注册类...在
src/test/resources
中,添加包含以下内容的META-INF/spring.factories
文件还要确保您的测试配置包含
spring.cloud.config.enabled=false
。wrrgggsh5#
我的解决方案适用于从Eureka 发现ConfigService的情况。
这个配置使应用程序在配置服务器中查找属性,要求它在Eureka 中的URL。在这样的应用程序中的测试被破坏,直到我找到一个工作的属性集。
我找到了一套工作:
spring.config.import
必须在环境SPRING_CONFIG_IMPORT=optional:configserver:http://app-name-in-eureka
中准确设置1.指定
spring.config.import = ${SPRING_CONFIG_IMPORT:}
无关紧要1.在测试中指定
spring.config.import
并不重要spring.cloud.config.fail-fast.enabled=false
-这就是诀窍