运行时当management.port=0时获取Spring Boot管理端口

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

我正在寻求有关如何在集成测试中将 management.port 属性设置为

0
时获取分配给为
actuator
端点提供服务的嵌入式 Tomcat 的端口的建议。

我使用的是 Spring Boot 1.3.2,具有以下

application.yml
配置:

server.port: 8080
server.contextPath: /my-app-context-path

management.port: 8081
management.context-path: /manage

...

我的集成测试然后用

@WebIntegrationTest
进行注释,将上面显示的端口设置为
0
:

@WebIntegrationTest({ "server.port=0", "management.port=0" })

在进行完整集成测试时,应使用以下实用程序类来访问应用程序配置:

@Component
@Profile("testing")
class TestserverInfo {
    
    @Value( '${server.contextPath:}' )
    private String contextPath;

    @Autowired
    private EmbeddedWebApplicationContext server;
    
    @Autowired
    private ManagementServerProperties managementServerProperties
    
    
    public String getBasePath() {
        final int serverPort = server.embeddedServletContainer.port
        
        return "http://localhost:${serverPort}${contextPath}"
    }
    
    public String getManagementPath() {
        // The following wont work here:
        // server.embeddedServletContainer.port -> regular server port
        // management.port -> is zero just as server.port as i want random ports

        final int managementPort = // how can i get this one ?
        final String managementPath = managementServerProperties.getContextPath()
        
        return "http://localhost:${managementPort}${managementPath}"
    }
}

我已经知道可以通过使用

local.server.port
来获取标准端口,并且名为
local.management.port
的管理端点似乎有一些等效项。但这句话似乎有不同的含义。 官方文档没有提到执行此操作的方法。

目前是否有任何未记录的方法来获取该管理端口?


解决方案编辑

当我使用 Spock Frameworkspock-spring 模块来测试我的 Spring Boot 应用程序时,我必须像这样初始化应用程序:

@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = MyApplication.class)

不知何故,spock-spring或测试初始化似乎影响了

@Value
注释的评估,因此
@Value("${local.management.port}")
导致了

java.lang.IllegalArgumentException:无法解析占位符 字符串值“${local.management.port}”中的“local.management.port”

通过您的解决方案,我知道该属性存在,因此我只需直接使用 Spring

Environment
在测试运行时检索属性值:

@Autowired
ManagementServerProperties managementServerProperties

@Autowired
Environment environment

public String getManagementPath() {
    final int managementPort = environment.getProperty('local.management.port', Integer.class)
    final String managementPath = managementServerProperties.getContextPath()
    
    return "http://localhost:${managementPort}${managementPath}"
}
spring spring-boot spock spring-boot-actuator
3个回答
13
投票

管理端口需要通过

@SpringBootTest
的属性字段设置为 0,然后使用
@LocalServerPort
和/或
@LocalManagementPort
注释在测试中获取端口。

示例:

从 Spring Boot 2.0.0 开始:

properties = {"management.server.port=0"}

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
        "management.server.port=0" })
public class HealthCheckIT {

    @Autowired
    private WebTestClient webTestClient;

    @LocalManagementPort
    int managementPort;

    @Test
    public void testManagementPort() {
        webTestClient
                .get().uri("http://localhost:" + managementPort + "/actuator/health")
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isOk();
    }
}

对于旧版本:[1.4.0 - 1.5.x]:

properties = {"management.port=0"}

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
    "management.port=0", "management.context-path=/admin" })
public class SampleTest {

    @LocalServerPort
    int port;

    @LocalManagementPort
    int managementPort;

6
投票

这就是我的做法,直接从我的测试类复制(我使用 RestAssured 进行断言):

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.WebIntegrationTest;

import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static com.jayway.restassured.RestAssured.get;
import static org.hamcrest.CoreMatchers.equalTo;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
@WebIntegrationTest(randomPort = true, value = {"management.port=0", "management.context-path=/admin"})
@DirtiesContext
public class ActuatorEndpointTest {

    @Value("${local.management.port}")
    private int localManagementPort;

    @Test
    public void actuatorHealthEndpointIsAvailable() throws Exception {

        String healthUrl = "http://localhost:" + localManagementPort + "/admin/health";
        get(healthUrl)
                .then()
                .assertThat().body("status", equalTo("UP"));
    }



}

0
投票

这是@magiccrafter 答案的更新,需要以下内容才能正常工作

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <scope>test</scope>
</dependency>

它也需要这个注释

@AutoConfigureWebTestClient

© www.soinside.com 2019 - 2024. All rights reserved.