Mockito的thenReturn()方法返回null值问题求助
刚接触Mockito遇到这种thenReturn返回null的问题太正常了,我结合你用@WebMvcTest的场景,给你梳理几个最可能的原因和解决办法:
1. 先检查setUp里的mock初始化是否完整
首先你得确认两件事:
- 你有没有给
moviesMock填充实际的Movie对象?如果只是new ArrayList<>()但没加元素,虽然不会返回null,但接口返回空列表;但如果连moviesMock本身都没初始化(比如忘了moviesMock = new ArrayList<>()),那thenReturn传的就是null,自然返回null。 - 你mock的方法签名和Controller里调用的完全匹配吗?比如Controller调用的是
movieService.getMoviesByYear(2023),但你mock的是movieService.getAllMovies(),这种不匹配的情况,Mockito会返回默认值null。
正确的初始化示例:
@Before public void setUp() { // 先初始化mock列表并添加数据 moviesMock = new ArrayList<>(); moviesMock.add(new Movie(1L, "星际穿越", "科幻")); moviesMock.add(new Movie(2L, "肖申克的救赎", "剧情")); // 确保mock的方法和Controller调用的完全一致 when(movieService.getAllMovies()).thenReturn(moviesMock); }
2. 确认@MockBean的使用逻辑
在@WebMvcTest中,@MockBean会自动替换Spring容器里的MovieService实例,所以要确保你的Controller是通过@Autowired注入MovieService的,而不是手动new了一个实例——如果Controller里自己new MovieService(),那它根本不会用到你mock的这个实例,自然返回null。
3. 检查Mockito静态方法的导入和使用
有没有不小心导入错了when方法?必须是org.mockito.Mockito.when,如果导入了其他包的同名方法,mock逻辑根本不会生效。
另外,你可以试试用doReturn替代thenReturn,这种写法在某些场景下(比如mock已经被调用过的方法)更可靠:
doReturn(moviesMock).when(movieService).getAllMovies();
4. 快速调试技巧
在测试方法里先直接调用mock的方法,看看返回值:
@Test public void testMock() { List<Movie> testResult = movieService.getAllMovies(); // 如果这里是null,说明mock设置有问题;如果正常,再排查MockMvc的请求映射 System.out.println(testResult); }
完整的测试示例参考
@RunWith(MockitoJUnitRunner.class) @WebMvcTest(value = MovieRestApiController.class, secure = false) public class MovieRestApiControllerTest { @Autowired private MockMvc mockMvc; @MockBean private MovieService movieService; private ArrayList<Movie> moviesMock; @Before public void setUp() { // 初始化测试数据 moviesMock = new ArrayList<>(); moviesMock.add(new Movie(1L, "Inception", "Sci-Fi")); moviesMock.add(new Movie(2L, "The Shawshank Redemption", "Drama")); // 设置mock返回值 when(movieService.getAllMovies()).thenReturn(moviesMock); } @Test public void testGetAllMoviesSuccess() throws Exception { // 先验证mock是否生效 Assert.assertEquals(2, movieService.getAllMovies().size()); // 再测试接口 mockMvc.perform(get("/api/movies") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$", hasSize(2))) .andExpect(jsonPath("$[0].title", is("Inception"))); } }
最后再提醒一句:一定要仔细核对Controller里调用的MovieService方法名、参数类型和数量,和你mock的完全一致,这是最容易踩的坑!
内容的提问来源于stack exchange,提问作者senham
相关产品推荐
相关产品推荐

