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

如何为Quarkus的ResponseExceptionMapper与ExceptionMapper编写测试获取代码覆盖率

两类异常映射器的单元测试实现示例

以下示例基于Junit 5编写,无需启动Web容器即可完成逻辑覆盖,可直接适配你项目中的现有Mapper实现。

1. ExceptionMapper 测试示例

首先是常见的自定义业务异常对应的ExceptionMapper实现参考:

// 自定义业务异常类
public class BizException extends RuntimeException {
    private final int code;
    public BizException(int code, String message) {
        super(message);
        this.code = code;
    }
    public int getCode() {
        return code;
    }
}

// ExceptionMapper实现类
@Provider
public class BizExceptionMapper implements ExceptionMapper<BizException> {
    @Override
    public Response toResponse(BizException e) {
        return Response.status(e.getCode())
                .entity(Map.of("code", e.getCode(), "message", e.getMessage()))
                .type(MediaType.APPLICATION_JSON)
                .build();
    }
}

对应的单元测试代码:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class BizExceptionMapperTest {
    // 直接实例化Mapper类,无需容器启动
    private final BizExceptionMapper exceptionMapper = new BizExceptionMapper();

    @Test
    public void testToResponseNormal() {
        // 构造测试入参
        int expectedCode = 400;
        String expectedMsg = "请求参数非法";
        BizException testException = new BizException(expectedCode, expectedMsg);

        // 执行映射逻辑
        Response result = exceptionMapper.toResponse(testException);

        // 校验返回结果是否符合预期
        assertEquals(expectedCode, result.getStatus());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, result.getMediaType());
        Map<String, Object> entity = (Map<String, Object>) result.getEntity();
        assertEquals(expectedCode, entity.get("code"));
        assertEquals(expectedMsg, entity.get("message"));
    }
}

2. ResponseExceptionMapper 测试示例

首先是ResponseExceptionMapper的实现参考,示例为处理5xx状态码的映射器:

@Provider
public class ServerErrorResponseMapper implements ResponseExceptionMapper<RuntimeException> {
    @Override
    public boolean handles(int status, MultivaluedMap<String, Object> headers) {
        // 仅处理500-599区间的服务端错误状态码
        return status >= 500 && status < 600;
    }

    @Override
    public RuntimeException toThrowable(Response response) {
        String errorInfo = response.readEntity(String.class);
        return new RuntimeException("服务端调用异常: " + errorInfo);
    }

    @Override
    public int getPriority() {
        return 10;
    }
}

对应的单元测试代码:

import org.junit.jupiter.api.Test;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.Response;
import static org.junit.jupiter.api.Assertions.*;

public class ServerErrorResponseMapperTest {
    private final ServerErrorResponseMapper responseMapper = new ServerErrorResponseMapper();

    @Test
    public void testHandlesStatus() {
        MultivaluedHashMap<String, Object> testHeaders = new MultivaluedHashMap<>();
        // 校验5xx状态码可被处理
        assertTrue(responseMapper.handles(500, testHeaders));
        assertTrue(responseMapper.handles(503, testHeaders));
        assertTrue(responseMapper.handles(599, testHeaders));
        // 校验非5xx状态码不会被处理
        assertFalse(responseMapper.handles(200, testHeaders));
        assertFalse(responseMapper.handles(404, testHeaders));
        assertFalse(responseMapper.handles(600, testHeaders));
    }

    @Test
    public void testToThrowable() {
        String expectedError = "数据库连接超时";
        Response testResponse = Response.status(500).entity(expectedError).build();

        RuntimeException resultException = responseMapper.toThrowable(testResponse);

        assertEquals("服务端调用异常: " + expectedError, resultException.getMessage());
    }

    @Test
    public void testGetPriority() {
        assertEquals(10, responseMapper.getPriority());
    }
}

补充说明:如果你的Mapper类中存在依赖注入的组件(比如日志类、配置类),可以用Mockito模拟对应依赖后注入到Mapper实例中,再执行测试即可。如果Mapper中存在多分支逻辑,针对每个分支单独构造测试用例就能覆盖所有代码路径。

内容的提问来源于stack exchange,提问作者Sandra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 13:45:03