SpringBoot中Mockito测试类出现NullPointerException问题求助
问题根源及解决步骤
1. JUnit版本注解冲突(MockMvc未初始化的直接原因)
测试类混用了JUnit 4的@Before和JUnit 5的@ExtendWith(MockitoExtension.class),JUnit 5不会执行JUnit 4的@Before方法,导致mockMvc始终为null。
修复方法:
将@Before替换为JUnit 5的@BeforeEach,导入对应包:
import org.junit.jupiter.api.BeforeEach; // ... @BeforeEach public void setUp() throws Exception { MockitoAnnotations.openMocks(this); this.mockMvc = MockMvcBuilders.standaloneSetup(bookController).build(); }
同时删除测试类中多余的JUnit 4相关导入(如org.junit.runner.RunWith、org.mockito.junit.MockitoJUnitRunner),已使用JUnit 5的扩展注解,无需保留JUnit 4的运行器配置。
2. 依赖冗余与版本冲突
- pom.xml中重复引入了两次junit依赖,删除其中一次;
spring-boot-starter-test已包含Mockito相关依赖,无需单独引入mockito-bom,删除该依赖避免版本冲突;
3. BookRepository的错误实现
手动实现JpaRepository的所有方法且多数返回null,会导致实际运行出错。Spring Data JPA仅需定义接口继承JpaRepository即可,无需手动实现:
@Repository public interface BookRepository extends JpaRepository<Book, Long> { // 无需编写任何方法,Spring自动生成实现逻辑 }
4. 测试类导入错误
测试中is匹配器导入错误,应使用Hamcrest的匹配器而非ByteBuddy的:
import static org.hamcrest.Matchers.is;
修复后的完整BookControllerTest示例
package com.example.junitrestapiapplication; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import java.util.Arrays; import java.util.List; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @ExtendWith(MockitoExtension.class) public class BookControllerTest { private MockMvc mockMvc; ObjectMapper objectMapper = new ObjectMapper(); ObjectWriter objectWriter = objectMapper.writer(); @Mock private BookRepository bookRepository; @InjectMocks private BookController bookController; Book RECORD_1 = new Book(1L, "Atomic Habits", "How to build better habits", 5); Book RECORD_2 = new Book(2L, "Thinking Fast and Slow", "How to create good mental models about thinking", 4); Book RECORD_3 = new Book(3L, "Grokking Algorithms", "learn algorithms the fun way", 5); @BeforeEach public void setUp() throws Exception { this.mockMvc = MockMvcBuilders.standaloneSetup(bookController).build(); } @Test public void getAllRecords_success() throws Exception { List<Book> records = Arrays.asList(RECORD_1, RECORD_2, RECORD_3); Mockito.when(bookRepository.findAll()).thenReturn(records); mockMvc.perform(MockMvcRequestBuilders .get("/book") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$", hasSize(3))) .andExpect(jsonPath("$[2].name", is("Grokking Algorithms"))); } }
内容的提问来源于stack exchange,提问作者Khare Ayushi
相关产品推荐
相关产品推荐

