You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:22:48