在 SpringBootTest 中禁用使用 spring.config.import 激活的配置服务客户端

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

我有一个裸露的 Spring Boot 应用程序

@SpringBootApplication
public class ClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}

使用以下内容连接到 Spring Cloud 配置服务器

application.yml

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)

问题在于 Spring Boot 2.4 新引入的属性

spring.config.import
的工作方式与所有其他属性不同。在我看来,只能添加值而不能删除。

有没有办法覆盖

spring.config.import
中的
SpringBootTest
?有没有办法只抑制与配置服务器的连接?

spring-boot spring-boot-test spring-cloud-config
5个回答
8
投票

仅供测试的解决方案

configserver.import = configserver:https://localhost:8888
spring.config.import = ${configserver.import}

这样您就可以在测试中将属性

configserver.import
设置为空字符串:

configserver.import = 

现在空的

spring.config.import
属性将不再被考虑。这甚至可以与生产环境中的
-D
JVM 启动参数覆盖一起使用。

在测试场景中,这必须与

spring.cloud.config.enabled=false
配对,因为 Spring Cloud 配置会检查至少一个以
spring.config.import
前缀开头的
configserver:
值,如果找不到匹配的属性,则不会让您启动.

错误

Caused by: java.lang.IllegalStateException: File extension is not known to any PropertySourceLoader

是通过

spring.cloud.config.enabled=false
禁用 Spring Cloud 配置引起的,因为这也会删除其处理所有
configserver:
前缀
spring.config.import
的 PropertySourceLoader bean。

生产环境 URL 替换的解决方案(还包括测试修复)

这是另一种变体,它允许在产品环境中切换配置服务器 url,因为多个

spring.config.import
定义不会互相覆盖: configserver.import = configserver:${CONFIG_SERVER_URL:https://localhost:8888} spring.config.import = ${configserver.import} spring.cloud.config.import-check.enabled = false

为什么需要
spring.cloud.config.import-check.enabled

?因为 Spring Cloud 配置需要

configserver:
中至少有一个
spring.config.import
前缀值,但在执行此检查之前不会
not
解析属性替换。因此,Spring Cloud 配置仅将 ${configserver.import} 视为字符串,并会阻止您的应用程序启动。
spring.cloud.config.import-check.enabled = false
防止上述检查。此外,环境变量
CONFIG_SERVER_URL
可用于覆盖产品环境中的本地主机配置服务器,同时如果
spring.config.import
在测试中设置为空,则仍允许
configserver.import
为空字符串。
/咆哮:真是一场噩梦


7
投票
https://github.com/spring-cloud/spring-cloud-config/issues/1877

在我看来,如果您需要在测试中覆盖它,那么不满意的解决方案是

永远不要

spring.config.import中放置

application.yml
特别是对于配置服务器,它只能放置在配置文件特定的配置文件或多文档的配置文件特定文档中

application.yml

。然后,您可以在生产中激活该配置文件,并在测试和开发阶段保持其不活动状态。

    


1
投票
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
中,但您将失去在测试中禁用它的能力,但是它会简单地忽略服务器已关闭的事实。
    


0
投票

当该类与前缀为

configserver:

 的导入匹配时,将返回可选资源
package com.roblovelock.spring.cloud.config; import org.springframework.boot.context.config.*; import org.springframework.cloud.config.client.ConfigServerConfigDataLocationResolver; import org.springframework.core.Ordered; import java.io.IOException; import java.util.List; public class NoOpCloudConfig implements ConfigDataLocationResolver<ConfigDataResource>, Ordered { @Override public boolean isResolvable(ConfigDataLocationResolverContext context, ConfigDataLocation location) { return location.hasPrefix(ConfigServerConfigDataLocationResolver.PREFIX); } @Override public List<ConfigDataResource> resolve(ConfigDataLocationResolverContext context, ConfigDataLocation location) throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException { return List.of(new NoOpResource()); } @Override public List<ConfigDataResource> resolveProfileSpecific(ConfigDataLocationResolverContext context, ConfigDataLocation location, Profiles profiles) throws ConfigDataLocationNotFoundException { return List.of(new NoOpResource()); } @Override public int getOrder() { return -1; } public static class NoOpResource extends ConfigDataResource{ private NoOpResource(){ super(true); } } public static class NoOpResourceLoader implements ConfigDataLoader<NoOpResource> { @Override public ConfigData load(ConfigDataLoaderContext context, NoOpResource resource) { return ConfigData.EMPTY; } } }

为了工作,我们需要使用 
spring.factories

...

 注册课程

src/test/resources

添加包含内容的

META-INF/spring.factories
文件
org.springframework.boot.context.config.ConfigDataLocationResolver=com.roblovelock.spring.cloud.config.NoOpCloudConfig
org.springframework.boot.context.config.ConfigDataLoader=com.roblovelock.spring.cloud.config.NoOpCloudConfig.NoOpResourceLoader

还要确保您的测试配置包含 
spring.cloud.config.enabled=false

    


0
投票

spring: application: name: app-name profiles: active: dev cloud: config: fail-fast: false discovery: enabled: true service-id: app-config-server uri: http://localhost:8888 eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ healthcheck: enabled: true

此配置使应用程序在配置服务器中查找属性,询问其在 Eureka 中的 URL。
在我找到一组有效的属性之前,此类应用程序中的测试被破坏了。

我找到了一个工作集:

    spring.config.import
  1. 必须在环境中准确设置
    SPRING_CONFIG_IMPORT=optional:configserver:http://app-name-in-eureka
    指定
  2. spring.config.import = ${SPRING_CONFIG_IMPORT:}
  3. 并不重要
    在测试中指定
  4. spring.config.import
  5. 并不重要
  6. spring.cloud.config.fail-fast.enabled=false
  7. - 这就是窍门
    
        
© www.soinside.com 2019 - 2024. All rights reserved.