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

如何对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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 14:22:57