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

Spring测试中如何Mock方法内的Mapper?解决空指针异常

问题解决指南

首先,你遇到的NullPointerException是因为Mock的envoyerMessage默认返回null,后续调用sendedMessageId.getValue()触发空指针。以下是分步解决方案:

1. 修复空指针异常

在测试方法中,用Mockito为envoyerMessage.execute()方法设置返回值,避免返回null:

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

// 其他必要导入

@Test
public void send() throws Exception {
    // 修正JSON语法错误(原JSON中id字段的1""是非法格式)
    String content = "{ \"id\": 1, \"message\": \"Test variable\" }";
    
    // 构造模拟的MessageId实例(根据你的实际类结构调整)
    MessageId mockMessageId = new MessageId(2L);
    
    // 让envoyerMessage.execute()返回模拟的MessageId
    when(envoyerMessage.execute(any(Message.class))).thenReturn(mockMessageId);
    
    this.mockMvc.perform(
            post("/api/message/add")
            .contentType(MediaType.APPLICATION_JSON)
            .content(content)
            .accept(MediaType.APPLICATION_JSON))
            // 原接口返回HttpStatus.CREATED(201),不是200,修正断言
            .andExpect(status().isCreated());
}

2. Mock WebMessageMapper

根据你的Mapper实现方式,分两种情况处理:

情况1:Mapper是Spring管理的Bean(如MapStruct指定componentModel="spring")

直接将Mapper声明为@MockBean,然后Stub转换方法:

@Tag("unitTest")
@WebMvcTest(MessageControllerV1.class)
public class MessageControllerV1Test {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private EnvoyerMessage envoyerMessage;

    @MockBean
    private LireMessage lireMessage;

    // 添加MockBean注解
    @MockBean
    private WebMessageMapper webMessageMapper;

    @Test
    public void send() throws Exception {
        String content = "{ \"id\": 1, \"message\": \"Test variable\" }";
        MessageId mockMessageId = new MessageId(2L);
        Message mockMessage = new Message();
        mockMessage.setMessage("Test variable");
        
        // Stub转换方法
        when(webMessageMapper.messageDtoToMessage(any(MessageDto.class))).thenReturn(mockMessage);
        when(envoyerMessage.execute(any(Message.class))).thenReturn(mockMessageId);
        
        this.mockMvc.perform(
                post("/api/message/add")
                .contentType(MediaType.APPLICATION_JSON)
                .content(content)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isCreated());
    }
}

情况2:Mapper是静态单例(如默认MapStruct实例)

使用Mockito的mockStatic来Mock静态实例:

import org.mockito.MockedStatic;

// 其他必要导入

@Test
public void send() throws Exception {
    String content = "{ \"id\": 1, \"message\": \"Test variable\" }";
    MessageId mockMessageId = new MessageId(2L);
    Message mockMessage = new Message();
    mockMessage.setMessage("Test variable");
    
    // Mock静态的WebMessageMapper.INSTANCE
    try (MockedStatic<WebMessageMapper> mockedMapper = org.mockito.Mockito.mockStatic(WebMessageMapper.class)) {
        WebMessageMapper mockMapper = org.mockito.Mockito.mock(WebMessageMapper.class);
        mockedMapper.when(WebMessageMapper::INSTANCE).thenReturn(mockMapper);
        when(mockMapper.messageDtoToMessage(any(MessageDto.class))).thenReturn(mockMessage);
        when(envoyerMessage.execute(any(Message.class))).thenReturn(mockMessageId);
        
        this.mockMvc.perform(
                post("/api/message/add")
                .contentType(MediaType.APPLICATION_JSON)
                .content(content)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isCreated());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:20:26