指定端口时,Spring Boot Actuator 端点的单元测试不起作用

Posted

技术标签:

【中文标题】指定端口时,Spring Boot Actuator 端点的单元测试不起作用【英文标题】:Unit testing of Spring Boot Actuator endpoints not working when specifying a port 【发布时间】:2016-11-25 02:48:41 【问题描述】:

最近我更改了 Spring Boot 属性以定义管理端口。 这样做,我的单元测试开始失败:​​(

我编写了一个单元测试来测试 /metrics 端点,如下所示:

@RunWith (SpringRunner.class)
@DirtiesContext
@SpringBootTest
public class MetricsTest 

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    /**
     * Called before each test.
     */
    @Before
    public void setUp() 
        this.context.getBean(MetricsEndpoint.class).setEnabled(true);
        this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
    

    /**
     * Test for home page.
     *
     * @throws Exception On failure.
     */
    @Test
    public void home()
            throws Exception 
        this.mvc.perform(MockMvcRequestBuilders.get("/metrics"))
                .andExpect(MockMvcResultMatchers.status().isOk());
    
        

以前这是通过的。添加后:

management.port=9001

测试开始失败:

home Failed: java.lang.AssertionError: Status expected: <200> but was: <404>

我尝试更改 @SpringBootTest 注释:

@SpringBootTest (properties = "management.port=<server.port>")

server.port 使用的号码在哪里。这似乎没有任何区别。

然后将属性文件中的 management.port 值更改为与 server.port 相同。结果一样。

让测试工作的唯一方法是从属性文件中删除 management.port。

有什么建议/想法吗?

谢谢

【问题讨论】:

因此为成功和失败案例添加了一些跟踪日志记录。在成功的情况下,我看到以下内容:TRACE [Test worker] --- org.springframework.test.web.servlet.TestDispatcherServlet: Testing handler map [org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping@2281521a] in DispatcherServlet with name 这在失败的情况下丢失了。所以我只能假设我使用了错误的值 MockMvcBuilders.webAppContextSetup(this.context) 【参考方案1】:

尝试使用

@SpringBootTest(properties = "management.port=")

@SpringBootTest 注释中定义的属性比应用程序属性中的属性具有higher precedence。 "management.port=" 将“取消设置”management.port 属性。 这样您就不必担心在测试中配置端口。

【讨论】:

您能否为您的答案添加一些解释?【参考方案2】:

您是否尝试将以下注释添加到您的测试类?

@TestPropertySource(properties = "management.port=0")

Check the following link for reference。

【讨论】:

【参考方案3】:

遇到同样的问题,您只需将 management.port 添加到您的 application-test.properties 中即可(将其设置为空值)

management.port=

通过注释类来确保在 JUnit 中使用测试配置文件

@ActiveProfiles("test")

【讨论】:

【参考方案4】:

对于 Spring 启动测试,我们需要指定它需要连接的端口。

默认情况下,它连接到server.port,如果执行器不同。

这可以通过

@SpringBootTest(properties = "server.port=8090")

application.properties我们指定管理端口如下

...
management.server.port=8090
...

【讨论】:

【参考方案5】:

是不是属性名有错误? 不应该 @TestPropertySource(properties = "management.server.port=...") 而不是 @TestPropertySource(properties = "management.port=..")

【讨论】:

【参考方案6】:

对于 Spring Boot 2.x,可以简化集成测试配置。

例如简单的自定义heartbeat端点

@Component
@Endpoint(id = "heartbeat")
public class HeartbeatEndpoint 

    @ReadOperation
    public String heartbeat() 
        return "";
    

此端点的集成测试在哪里

@SpringBootTest(
        classes = HeartbeatEndpointTest.Config.class,
        properties = 
                "management.endpoint.heartbeat.enabled=true",
                "management.endpoints.web.exposure.include=heartbeat"
        )
@AutoConfigureMockMvc
@EnableAutoConfiguration
class HeartbeatEndpointTest 

    private static final String ENDPOINT_PATH = "/actuator/heartbeat";

    @Autowired
    private MockMvc mockMvc;

    @Test
    void testHeartbeat() throws Exception 
        mockMvc
                .perform(get(ENDPOINT_PATH))
                .andExpect(status().isOk())
                .andExpect(content().string(""));
    

    @Configuration
    @Import(ProcessorTestConfig.class)
    static class Config 

        @Bean
        public HeartbeatEndpoint heartbeatEndpoint() 
            return new HeartbeatEndpoint();
        

    

    

【讨论】:

感谢分享。如何添加负面用例?【参考方案7】:

我遇到了同样的问题并尝试了几件事,但这就是我能够在不更改 application.yaml 的情况下解决我的问题的方法

执行器端点示例

@Component
@RestControllerEndpoint(id = "endpoint")
public class SampleEndpoint

    @GetMapping
    public String sampleEndpoint()
      return ""
    

单元测试用例

@RunWith(SpringRunner.class)
@SpringBootTest(
    classes = SampleEndpointTest.Config.class,
    properties = "management.server.port="
)
@AutoConfigureMockMvc
public class SampleEndpointTest

    @Autowired
    private MockMvc mockMvc;

    @SpringBootApplication(scanBasePackageClasses = SampleEndpoint.class)
    public static class Config
    
    

    @Test
    public void testSampleEndpoint() throws Exception
    

        mockMvc.perform(
            MockMvcRequestBuilders.get("/actuator/enpoint").accept(APPLICATION_JSON)
        ).andExpect(status().isOk());
    

【讨论】:

【参考方案8】:

指南指出这可以通过@AutoConfigureMetrics 来实现。 我也跟着搬家了。

无论您的类路径如何,在使用 @SpringBootTest 时,计量注册表(内存中支持的除外)都不会自动配置。 如果您需要在集成测试中将指标导出到不同的后端,请使用 @AutoConfigureMetrics 对其进行注释。

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.metrics

【讨论】:

【参考方案9】:

现在必须手动启用 info 端点,确保 SpringBootTest 标记在属性中包含此内容,如下所示:

@SpringBootTest(
        properties = 
                "management.info.env.enabled=true" ,
                "management.endpoints.web.exposure.include=info, health"
        )

【讨论】:

以上是关于指定端口时,Spring Boot Actuator 端点的单元测试不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 项目启动指定 HTTP 端口的几种方式

Spring Boot 项目启动指定 HTTP 端口的几种方式

Spring Boot - 如何在不使用 spring 注释的情况下在运行时获取端口

使用响应式框架运行 Spring Boot 应用程序时打开端口

使用属性 server.port=0 运行 spock 测试时如何找到 Spring Boot 容器的端口

使用 Spring Boot Java 端口 8080 上的 Tomcat 失败