如何使用Spring Boot测试单个JAX-RS/Jersey端点?
测试单个JAX-RS/Jersey端点(真实Web环境)
这和使用@WebMvcTest测试单个Spring控制器的思路类似,区别在于我们会使用真实Web环境而非模拟环境。
- 我们基于一个Web层测试场景的示例展开,但示例中使用JAX-RS/Jersey端点而非Spring控制器。
- 核心需求是把现有的应用级测试改造为仅针对单个端点的测试。
应用代码示例
端点实现
package org.example; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import org.springframework.stereotype.Component; @Component @Path("/") public final class GreetingEndpoint { @GET public String helloWorld() { return "Hello, world!"; } }
Jersey配置类
package org.example; import org.glassfish.jersey.server.ResourceConfig; import org.springframework.stereotype.Component; @Component public final class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(GreetingEndpoint.class); // 实际场景中会注册更多其他端点 } }
应用启动类
package org.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GreetingApplication { public static void main(String[] args) { SpringApplication.run(GreetingApplication.class, args); } }
现有应用级测试代码
这是可以正常运行的全应用测试用例:
package org.example; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public final class GreetingApplicationTest { @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; @Test void helloWorld() { assertThat(restTemplate.getForObject(String.format("http://localhost:%d", port), String.class)) .isEqualTo("Hello, world!"); } }
单个端点测试的实现方案
实际场景中JerseyConfig会注册多个端点,我们需要编写仅针对单个端点的测试,同时保留JUnit Jupiter、AssertJ和Spring Boot测试库的技术栈(类似@WebMvcTest的效果,但使用真实Web环境)。
步骤1:创建测试专用的Jersey配置
在测试包下创建仅注册目标端点的配置类,替代原有全局配置:
package org.example; import org.glassfish.jersey.server.ResourceConfig; import org.springframework.context.annotation.Configuration; @Configuration public class TestJerseyConfig extends ResourceConfig { public TestJerseyConfig() { // 仅注册需要测试的GreetingEndpoint register(GreetingEndpoint.class); } }
步骤2:编写单个端点测试类
通过@SpringBootTest排除原有配置,导入测试专用配置,实现仅加载目标端点的测试环境:
package org.example; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.context.annotation.Import; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, exclude = JerseyConfig.class) @Import(TestJerseyConfig.class) public class GreetingEndpointTest { @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; @Test void helloWorldReturnsCorrectMessage() { String response = restTemplate.getForObject(String.format("http://localhost:%d", port), String.class); assertThat(response).isEqualTo("Hello, world!"); } }
方案说明
- 使用
@SpringBootTest(exclude = JerseyConfig.class)排除原有全局Jersey配置,避免加载所有端点。 - 通过
@Import(TestJerseyConfig.class)导入仅包含目标端点的测试配置,确保测试环境只启动需要验证的端点。 - 保留真实Web环境(
WebEnvironment.RANDOM_PORT),和应用级测试使用相同的测试栈,保证测试结果的真实性。
内容的提问来源于stack exchange,提问作者MikeW
相关产品推荐
相关产品推荐

