QuarkusTest中@Mock失效,Mock @Context字段遇NPE及代理异常
解决Quarkus中JAX-RS过滤器ApiMetrics的单元测试问题
针对你在测试实现ContainerRequestFilter和ContainerResponseFilter的ApiMetrics类时遇到的Mock注入异常、空指针及代理类错误,以下是可行的解决方案:
问题根源
Quarkus中JAX-RS过滤器通过@Context注入的ResourceInfo和HttpServerRequest是容器管理的代理对象,普通Mockito Mock方式无法适配Quarkus的依赖注入机制,容易出现注入失败或代理冲突。
方案1:使用@InjectMock进行依赖Mock(单元测试)
步骤1:调整过滤器类的字段可见性
确保ApiMetrics中@Context注入的字段为包私有或public,或添加setter方法,方便测试时注入Mock实例:
@Provider public class ApiMetrics implements ContainerRequestFilter, ContainerResponseFilter { @Context ResourceInfo resourceInfo; // 包私有,测试类同包可访问 @Context HttpServerRequest httpServerRequest; // 过滤器逻辑实现 }
步骤2:编写测试类
使用@QuarkusTest + @InjectMock组合,让Quarkus将Mock实例注入到过滤器中,同时用Mockito Stub必要的方法:
@QuarkusTest public class ApiMetricsTest { @InjectMock ResourceInfo resourceInfo; @InjectMock HttpServerRequest httpServerRequest; @Inject ApiMetrics apiMetrics; @Test void testRequestFilter() throws IOException { // Stub ResourceInfo的方法,模拟获取资源端点的方法 Method testMethod = MyResource.class.getMethod("testEndpoint"); when(resourceInfo.getResourceMethod()).thenReturn(testMethod); // Stub HttpServerRequest的方法,模拟请求路径 when(httpServerRequest.getPath()).thenReturn("/api/test"); // 模拟请求上下文 ContainerRequestContext requestContext = Mockito.mock(ContainerRequestContext.class); // 执行过滤器逻辑 apiMetrics.filter(requestContext); // 验证逻辑(比如是否调用了requestContext.proceed(),或指标是否被记录) verify(requestContext, times(1)).proceed(); } @Test void testResponseFilter() throws IOException { // 类似请求过滤器的Stub逻辑 ContainerRequestContext requestContext = Mockito.mock(ContainerRequestContext.class); ContainerResponseContext responseContext = Mockito.mock(ContainerResponseContext.class); apiMetrics.filter(requestContext, responseContext); // 验证响应处理逻辑 } }
方案2:发送真实HTTP请求(集成测试)
如果不需要Mock依赖,可直接发送真实请求,让Quarkus自动注入ResourceInfo和HttpServerRequest的真实实例,验证过滤器的整体行为:
@QuarkusTest public class ApiMetricsIntegrationTest { @Test void testMetricsRecording() { // 发送测试请求 given() .when().get("/api/test") .then() .statusCode(200); // 验证指标是否被正确记录(比如通过Micrometer的MeterRegistry检查) // 示例:如果用Micrometer,可注入MeterRegistry查询指标 // MeterRegistry registry = Arc.container().instance(MeterRegistry.class).get(); // assertThat(registry.get("api.requests.total").counter().count()).isEqualTo(1); } }
常见问题说明
- @Mock导致空指针:普通
@Mock是Mockito原生注解,无法自动注入到Quarkus容器管理的ApiMetrics实例中,需用@InjectMock让Quarkus完成注入。 - 手动Mock出现LoggableFailure:
HttpServerRequest是Quarkus内部代理类,手动Mock会与容器的代理机制冲突,使用@InjectMock可避免此问题。 - @Inject/@InjectMock依赖错误:确保测试类中
ApiMetrics、ResourceInfo、HttpServerRequest的依赖都被Quarkus正确识别,检查过滤器类是否标注@Provider,测试类是否添加@QuarkusTest。
内容的提问来源于stack exchange,提问作者Vanshaj Behl
相关产品推荐
相关产品推荐

