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

Spring Boot JUnit5单元测试getSerieById失败,verify校验不通过求助

问题描述

使用Spring Boot与JUnit5编写的getSerieByIdSimplifiedTest单元测试无法正常运行:控制器和SerieService实现逻辑无问题,但保留verify校验时就会报错,移除verify则测试正常。已通过@MockBean注入SerieService,却仍出现如下错误:

Wanted but not invoked: vidaria.services.SerieService#0 bean.getSeriesById(1L );

测试代码如下:

package com.garmanaz.vidaria.controllers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.garmanaz.vidaria.entities.Serie;
import com.garmanaz.vidaria.services.SerieService;
import com.garmanaz.vidaria.utils.JWT.JwtRequestFilter;
import com.garmanaz.vidaria.utils.JWT.JwtTokenUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(controllers = SerieController.class)
@WithMockUser(username = "john", roles = {"USER"})
public class SerieControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@MockBean
private SerieService serieService;

@MockBean
private JwtTokenUtil jwtTokenUtil;

@MockBean
private JwtRequestFilter jwtRequestFilter;

@Autowired
private SerieController serieController;

@MockBean
private RestTemplateBuilder restTemplateBuilder;

@BeforeEach
void setUp() {
    ReflectionTestUtils.setField(serieController, "serieService", serieService);
}

@Test
void verifyMockInjection() {
    SerieService injectedService = (SerieService) ReflectionTestUtils.getField(serieController, "serieService");
    System.out.println("Injected SerieService: " + injectedService);
    assertSame(injectedService, serieService, "The injected service is not the mock");
}

@Test
void getSerieByIdSimplifiedTest() throws Exception {
    long serieId = 1L;
    Serie mockSerie = Serie.builder()
            .id(serieId)
            .title("Test Serie")
            .build();

    when(serieService.getSeriesById(serieId)).thenReturn(mockSerie);

    mockMvc.perform(get("/series/{serieId}", serieId)
                    .contentType("application/json"))
            .andDo(print())
            .andExpect(status().isOk());

    verify(serieService, times(1)).getSeriesById(1L);
}

}
问题排查与解决

1. 移除多余的手动注入代码

@WebMvcTest注解会自动将@MockBean声明的SerieService注入到SerieController中,不需要在setUp方法里用ReflectionTestUtils手动设置。这种重复操作可能导致注入的Mock实例不一致,使得实际调用的Service和你verify的不是同一个对象。

解决方法:删除setUp方法以及verifyMockInjection测试方法,让Spring自动完成MockBean的注入。

2. 明确参数匹配规则

Mockito的参数匹配默认是严格匹配的,建议在when和verify中使用eq()匹配器明确指定参数,避免因基本类型/包装类型差异、重载方法等导致的匹配失败:

when(serieService.getSeriesById(eq(serieId))).thenReturn(mockSerie);
// ...
verify(serieService, times(1)).getSeriesById(eq(serieId));

3. 确认请求路径与控制器映射完全匹配

检查SerieController类或方法上的@RequestMapping注解,确认测试中的请求路径(/series/{serieId})与控制器的映射完全一致。如果控制器类上有前缀(比如@RequestMapping("/api")),测试请求需要加上对应前缀,例如/api/series/{serieId}。

可以通过andDo(print())打印的日志,查看请求是否真的路由到了目标控制器方法。

4. 校验方法名拼写一致性

确认SerieService中的方法名确实是getSeriesById,且控制器中调用的是该方法,避免因拼写错误导致Mock未被触发。

修正后的测试代码示例

package com.garmanaz.vidaria.controllers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.garmanaz.vidaria.entities.Serie;
import com.garmanaz.vidaria.services.SerieService;
import com.garmanaz.vidaria.utils.JWT.JwtRequestFilter;
import com.garmanaz.vidaria.utils.JWT.JwtTokenUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(controllers = SerieController.class)
@WithMockUser(username = "john", roles = {"USER"})
public class SerieControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @MockBean
    private SerieService serieService;

    @MockBean
    private JwtTokenUtil jwtTokenUtil;

    @MockBean
    private JwtRequestFilter jwtRequestFilter;

    @MockBean
    private RestTemplateBuilder restTemplateBuilder;

    @Test
    void getSerieByIdSimplifiedTest() throws Exception {
        long serieId = 1L;
        Serie mockSerie = Serie.builder()
                .id(serieId)
                .title("Test Serie")
                .build();

        when(serieService.getSeriesById(eq(serieId))).thenReturn(mockSerie);

        mockMvc.perform(get("/series/{serieId}", serieId)
                        .contentType("application/json"))
                .andDo(print())
                .andExpect(status().isOk());

        verify(serieService, times(1)).getSeriesById(eq(serieId));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:32:15