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)
问题分析
- 依赖缺失:报错提示找不到
jakarta/servlet/ServletException类,说明测试环境缺少Jakarta Servlet API相关依赖,MockMvc运行需要该依赖支持。 - 测试逻辑错误:
setup方法初始化MockMvc时,新建了MyCommonServiceController实例,而非使用@InjectMocks注解注入的myController,导致@Mock标记的myCommonService未被注入到控制器中,测试逻辑会失效。 - 代码规范问题:
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
相关产品推荐
相关产品推荐

