Spring测试中@Bean方法未调用,Mockito抛出MissingMethodInvocationException异常
MissingMethodInvocationException 问题 我帮你分析下这个报错的核心原因:你在when()里调用的对象根本不是Mockito生成的Mock实例,大概率是Spring上下文把真实的MyRepository Bean注入进来了,导致你试图Mock一个真实对象,自然会抛出这个异常。结合你的场景(测试REST控制器+@WithUserDetails授权),给你一套靠谱的解决步骤:
第一步:确认测试类的正确注解
测试REST控制器时,别用@SpringBootTest(它会加载完整Spring上下文,包括真实的Repository),改用@WebMvcTest——这个注解只会加载控制器相关的Bean,Repository层的Bean需要我们手动Mock。
第二步:正确Mock你的Repository
用Spring Boot提供的@MockBean注解来MockMyRepository,它会自动把Mock实例注入到Spring上下文,替换掉真实的Repository Bean,这样你的控制器就会使用Mock的实例了。
正确的测试类示例
// 只加载你要测试的那个REST控制器 @WebMvcTest(YourTargetRestController.class) // 你的授权注解,确保UserDetailsService能正确加载指定用户 @WithUserDetails("testAuthorizedUser") class YourRestControllerAuthorizationTest { // 注入MockMvc用来模拟HTTP请求 @Autowired private MockMvc mockMvc; // 关键:用@MockBean生成MyRepository的Mock实例,Spring会自动注入到控制器 @MockBean private MyRepository myRepository; @Test void testAuthorizedEndpointAccess() throws Exception { // 先给Mock的Repository定义方法行为 when(myRepository.findSomethingByUserId(anyLong())) .thenReturn(yourMockedReturnObject); // 模拟HTTP请求,测试授权和接口逻辑 mockMvc.perform(get("/api/your/protected/endpoint") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.data").value("expectedValue")); } }
常见错误排查
错误1:用@Autowired注入了真实的Repository
如果你写了@Autowired private MyRepository myRepository;,那这个是Spring初始化的真实Repository实例,不是Mock,调用when()肯定会报错。解决:把@Autowired换成@MockBean。
错误2:手动创建Mock但没注入到控制器
比如你自己用Mockito.mock(MyRepository.class)创建了Mock,但没让Spring把它注入到控制器里,控制器还是用的真实实例。解决:要么用@MockBean,要么用@Mock+@InjectMocks(适合纯单元测试,不用MockMvc的场景):
@Mock private MyRepository myRepository; @InjectMocks private YourTargetRestController controller; @BeforeEach void setUp() { // 初始化Mock和注入 MockitoAnnotations.openMocks(this); }
错误3:测试类用了@SpringBootTest
@SpringBootTest会加载完整的Spring上下文,包括你的真实Repository(可能还会连接数据库),这时候即使你用了@Mock,也不会替换掉真实的Bean。解决:换成@WebMvcTest。
额外提醒
@WithUserDetails需要你的UserDetailsService能正确加载指定的用户名,不然授权会失败,但这个和当前的Mockito异常无关,如果你授权环节有问题可以再排查这块。
内容的提问来源于stack exchange,提问作者LimitX

