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

JUnit 5中使用MockMvcBuilders.standaloneSetup()遇NoClassDefFoundError问题

Controller测试类报错解决

测试代码

public class MyControllerTest {
    @InjectMocks
    private MyController myController;

    @Mock
    private MyCommonService myCommonService;

    private MockMvc mockMvc;

    @BeforeEach
    public void setup() {
        MockitoAnnotations.openMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup
                (new MyCommonServiceController()).build();
    }

    @Test
    public void testDataReturnsOk() throws Exception {
        when(myCommonService.getData())
                .thenReturn(Collections.singletonList(new myDto()));

        mockMvc.perform(get("/data"))
                .andExpect(status().isOk());
    }
}

报错信息

java.lang.NoClassDefFoundError: jakarta/servlet/ServletException

    at org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup(MockMvcBuilders.java:76)
    at com.markitclear.cui.cp.rest.controller.CPCommonServiceControllerTest.setup(CPCommonServiceControllerTest.java:36)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

问题分析

  1. 依赖缺失:报错提示找不到jakarta/servlet/ServletException类,说明测试环境缺少Jakarta Servlet API相关依赖,MockMvc运行需要该依赖支持。
  2. 测试逻辑错误:setup方法初始化MockMvc时,新建了MyCommonServiceController实例,而非使用@InjectMocks注解注入的myController,导致@Mock标记的myCommonService未被注入到控制器中,测试逻辑会失效。
  3. 代码规范问题:myDto类名不符合Java大驼峰命名规范,应改为MyDto。

修复步骤

1. 补充依赖

如果是Spring Boot项目,确保构建文件中包含spring-boot-starter-test依赖,它已包含所需的Servlet API测试依赖:
Maven(pom.xml):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Gradle(build.gradle):

testImplementation 'org.springframework.boot:spring-boot-starter-test'

如果是非Spring Boot项目,需单独添加Jakarta Servlet API测试依赖:
Maven:

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>5.0.0</version>
    <scope>test</scope>
</dependency>

2. 修正MockMvc初始化逻辑

将setup方法中的new MyCommonServiceController()替换为myController,确保Mock服务被正确注入:

@BeforeEach
public void setup() {
    MockitoAnnotations.openMocks(this);
    mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
}

3. 修正Dto类名

把new myDto()改为new MyDto(),遵循Java命名规范。

修正后的完整测试代码:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import java.util.Collections;
import static org.mockito.Mockito.when;

public class MyControllerTest {
    @InjectMocks
    private MyController myController;

    @Mock
    private MyCommonService myCommonService;

    private MockMvc mockMvc;

    @BeforeEach
    public void setup() {
        MockitoAnnotations.openMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
    }

    @Test
    public void testDataReturnsOk() throws Exception {
        when(myCommonService.getData())
                .thenReturn(Collections.singletonList(new MyDto()));

        mockMvc.perform(MockMvcRequestBuilders.get("/data"))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:30:57