为何SpringBootTest指定DEFINED_PORT时无法结合TestRestTemplate做集成测试?
在DEFINED_PORT模式下使用TestRestTemplate的解决方案
可以在DEFINED_PORT模式下使用TestRestTemplate,只是默认自动配置逻辑不会在该模式下自动注册TestRestTemplate Bean,需要通过手动创建或强制启用自动配置来解决。
原因分析
Spring Boot的TestRestTemplateAutoConfiguration自动配置类,仅在webEnvironment为RANDOM_PORT时自动创建并配置TestRestTemplate Bean——因为此时框架明确知道要连接当前测试启动的嵌入式服务器(随机端口)。而DEFINED_PORT模式下,框架无法确定你是要连接当前测试启动的服务器还是外部服务,因此不会自动注入该Bean。
解决方案
方法1:手动创建TestRestTemplate实例
在测试类中手动初始化TestRestTemplate,并指定目标服务的基础URL:
@ActiveProfiles("integration-test") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class SampleApiControllerIntegrationTest { @LocalServerPort private Integer port; private TestRestTemplate testRestTemplate; @BeforeEach void setUp() { this.testRestTemplate = new TestRestTemplate(); // 绑定到当前测试启动的服务端口 this.testRestTemplate.getRestTemplate().setUriTemplateHandler( new DefaultUriBuilderFactory("http://localhost:" + port) ); } // 测试方法示例 @Test void testApi() { ResponseEntity<String> response = testRestTemplate.getForEntity("/api/sample", String.class); // 断言逻辑... } }
方法2:强制启用自动配置
通过@AutoConfigureTestRestTemplate注解强制框架自动配置TestRestTemplate,再手动指定基础URL:
@ActiveProfiles("integration-test") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @AutoConfigureTestRestTemplate public class SampleApiControllerIntegrationTest { @LocalServerPort private Integer port; @Autowired private TestRestTemplate testRestTemplate; @BeforeEach void setUp() { // 绑定到当前测试启动的服务端口 testRestTemplate.getRestTemplate().setUriTemplateHandler( new DefaultUriBuilderFactory("http://localhost:" + port) ); } // 测试方法... }
方法3:自定义配置类注册Bean
创建配置类定义TestRestTemplate Bean,再在测试类中导入:
@ActiveProfiles("integration-test") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @Import(TestRestTemplateConfig.class) public class SampleApiControllerIntegrationTest { @Autowired private TestRestTemplate testRestTemplate; // 测试方法... } @Configuration class TestRestTemplateConfig { @Value("${server.port:8060}") // 读取配置文件中的端口,默认8060 private Integer serverPort; @Bean public TestRestTemplate testRestTemplate() { TestRestTemplate template = new TestRestTemplate(); template.getRestTemplate().setUriTemplateHandler( new DefaultUriBuilderFactory("http://localhost:" + serverPort) ); return template; } }
内容的提问来源于stack exchange,提问作者Tohid Makari
相关产品推荐
相关产品推荐

