JUnit中Mock Spring Security遇异常:用户注册服务测试报错
解决JUnit中Mock Spring Security组件的MissingMethodInvocationException问题
问题根源分析
你遇到的MissingMethodInvocationException本质是**when()方法里传入的不是Mock对象的方法调用**,结合你的场景,大概率是以下几个原因:
- 未Mock
AuthenticationManager组件(你的AuthServiceImpl里用到了它,但测试代码没处理) - Mock对象未被正确初始化
- 静态类
SecurityContextHolder的方法没做Mock/上下文设置 when()的写法错误(比如调用了真实对象的方法而非Mock对象)
分步解决方案
1. 确保Mock对象正确初始化
测试类必须添加Mockito的扩展注解,让Mock对象被正确创建:
// JUnit 5 @ExtendWith(MockitoExtension.class) public class AuthServiceImplTest { // 要Mock的组件 @Mock private UserRepository userRepository; @Mock private JwtTokenProvider jwtTokenProvider; @Mock // 关键:你之前可能漏了Mock这个AuthenticationManager private AuthenticationManager authenticationManager; // 注入Mock到待测试的服务 @InjectMocks private AuthServiceImpl authService; // 测试方法... }
如果是JUnit 4,替换成@RunWith(MockitoJUnitRunner.class)。
2. Mock AuthenticationManager的authenticate方法
在测试方法里,对authenticationManager.authenticate()做Stub,避免调用真实逻辑:
@Test void testRegister() { // 构造测试用的Authentication对象 Authentication mockAuth = new UsernamePasswordAuthenticationToken("testUser", "testPass"); // Stub authenticate方法,返回Mock的Authentication when(authenticationManager.authenticate(any(Authentication.class))) .thenReturn(mockAuth); // 其他Mock逻辑,比如userRepository.save() User testUser = new User("testUser", "testPass"); when(userRepository.save(any(User.class))).thenReturn(testUser); // 执行测试 authService.register(testUser); // 断言逻辑... }
3. 处理SecurityContextHolder的静态方法
SecurityContextHolder是静态类,Mockito-core无法直接Mock静态方法,有两种处理方式:
- 方式一:用Spring Security Test工具类设置上下文
利用spring-security-test提供的工具直接设置SecurityContext:@Test void testRegister() { // 构造Mock的Authentication Authentication mockAuth = new UsernamePasswordAuthenticationToken("testUser", "testPass"); // 设置SecurityContext SecurityContext context = SecurityContextHolder.createEmptyContext(); context.setAuthentication(mockAuth); SecurityContextHolder.setContext(context); // 其他测试逻辑... } - 方式二:用Mockito-inline Mock静态方法
如果你用的是Mockito 3.4+,可以引入mockito-inline依赖,然后Mock静态方法:
测试代码里的写法:<!-- pom.xml添加依赖 --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency>@Test void testRegister() { try (MockedStatic<SecurityContextHolder> mockedStatic = Mockito.mockStatic(SecurityContextHolder.class)) { SecurityContext mockContext = mock(SecurityContext.class); Authentication mockAuth = new UsernamePasswordAuthenticationToken("testUser", "testPass"); mockedStatic.when(SecurityContextHolder::getContext).thenReturn(mockContext); when(mockContext.getAuthentication()).thenReturn(mockAuth); // 其他测试逻辑... } }
4. 检查when()的写法细节
确保when()里的调用是Mock对象的方法,比如不要写成:
// 错误:调用了真实对象的方法 when(authService.someMethod()).thenReturn(...);
必须是Mock对象的方法调用,比如:
// 正确:调用Mock的userRepository的方法 when(userRepository.save(any(User.class))).thenReturn(testUser);
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

