如何对Micronaut错误处理器进行单元测试?
如何对Micronaut错误处理器进行单元测试?
兄弟,我太懂你踩的这个坑了——直接调用控制器的方法确实绕开了Micronaut的错误处理管道,导致异常直接炸出来,根本到不了你的@Error处理器。要测试错误处理器,得让请求走完整的框架流程才行,试试下面的方案:
核心问题:直接调用方法跳过了框架处理链
你之前直接调用instance.post(jsonData)本质就是普通的Java方法调用,而Micronaut的@Error注解处理器是绑定在请求处理的拦截器链里的,这种直接调用完全绕开了这个链条,所以异常直接抛出导致测试失败,根本不会触发错误处理器生成响应。
正确姿势:用@MicronautTest + HttpClient模拟真实请求
Micronaut专门提供了@MicronautTest注解,可以启动一个轻量的嵌入式容器,然后注入HttpClient发送真实HTTP请求,这样整个请求流程都会走框架的处理逻辑,包括错误处理器的触发。
场景1:测试JSON格式错误触发的错误处理器
这种情况根本不需要Mock Service,因为框架在解析@Body参数时,发现JSON格式不对就会直接抛出JsonProcessingException,自动触发你的错误处理器。测试代码示例:
import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; import io.micronaut.http.MediaType; import io.micronaut.http.client.HttpClient; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @MicronautTest class DesignControllerTest { @Inject HttpClient client; @Test void post_malformedJson_returnsBadRequest() { // 构造格式错误的JSON String malformedJson = "var: 37"; // 构建POST请求,指定Content-Type为JSON HttpRequest<String> request = HttpRequest.POST("/your-controller-path", malformedJson) .contentType(MediaType.APPLICATION_JSON); // 发送请求并获取响应 HttpResponse<ErrorModel> response = client.toBlocking().exchange(request, ErrorModel.class); // 验证状态码 assertEquals(HttpStatus.BAD_REQUEST, response.getStatus()); // 验证错误信息(根据你实际的异常信息调整) assertNotNull(response.body()); assertTrue(response.body().getMessage().contains("Malformed JSON")); } }
场景2:测试Service抛出异常触发的错误处理器
如果要测试Service层抛出JsonProcessingException的情况,可以用@MockBean替换真实的Service,让它抛出指定异常:
import io.micronaut.context.annotation.MockBean; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; import io.micronaut.http.MediaType; import io.micronaut.http.client.HttpClient; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @MicronautTest class DesignControllerTest { @Inject HttpClient client; @Inject DesignService designService; // 用Mock替换真实的DesignService @MockBean(DesignService.class) DesignService mockDesignService() { return mock(DesignService.class); } @Test void post_serviceThrowsJsonException_returnsError() throws JsonProcessingException { String validJson = "{\"name\": \"test-design\"}"; // 让Mock的Service抛出异常 doThrow(new JsonProcessingException("Service JSON processing failed")) .when(designService).save(anyString()); HttpRequest<String> request = HttpRequest.POST("/your-controller-path", validJson) .contentType(MediaType.APPLICATION_JSON); HttpResponse<ErrorModel> response = client.toBlocking().exchange(request, ErrorModel.class); assertEquals(HttpStatus.BAD_REQUEST, response.getStatus()); assertEquals("Service JSON processing failed", response.body().getMessage()); } }
关键提示
@MicronautTest会启动嵌入式容器,确保所有框架组件(包括错误处理器)都被正确初始化。- 必须用
HttpClient发送请求,模拟真实的HTTP调用,这样请求才会经过Micronaut的拦截器链,触发@Error注解的处理器。 - 不同场景区分处理:请求体解析错误不需要Mock Service;Service层异常则通过
@MockBean替换真实服务即可。
备注:内容来源于stack exchange,提问作者SenorPez
相关产品推荐
相关产品推荐

