Spring Boot测试中如何快速Mock @SpyBean标注实例的所有方法
可以通过反射封装通用工具方法实现需求,具体实现如下:
1. 依赖说明
Spring Boot 测试场景默认已集成 Mockito 核心依赖,无需额外引入。
2. 实现通用mockAllMethods工具方法
import org.mockito.Mockito; import java.lang.reflect.Method; import java.util.Arrays; public class MockUtils { /** * 批量Stub Spy对象的所有方法:void方法默认doNothing,非void方法返回对应类型的默认值 * @param spyObj 被@SpyBean/@Spy修饰的Spy对象 */ public static <T> void mockAllMethods(T spyObj) { // Spy是代理类,需要取父类即原始业务类 Class<?> clazz = spyObj.getClass().getSuperclass(); Arrays.stream(clazz.getDeclaredMethods()) // 过滤编译器生成的合成方法,可根据需求添加自定义过滤规则 .filter(method -> !method.isSynthetic()) .forEach(method -> { try { // 生成参数匹配器,匹配所有入参场景 Object[] args = Arrays.stream(method.getParameterTypes()) .map(Mockito::any) .toArray(); // void方法默认无操作 if (method.getReturnType() == Void.TYPE) { Mockito.doNothing().when(spyObj, method.getName(), args); return; } // 非void方法返回对应类型默认值 Object defaultValue = getDefaultValue(method.getReturnType()); Mockito.doReturn(defaultValue).when(spyObj, method.getName(), args); } catch (Exception e) { throw new RuntimeException("Mock方法失败: " + method.getName(), e); } }); } /** * 获取基础类型默认值,引用类型默认返回null */ private static Object getDefaultValue(Class<?> returnType) { if (!returnType.isPrimitive()) { return null; } if (returnType == boolean.class) return false; if (returnType == int.class) return 0; if (returnType == long.class) return 0L; if (returnType == double.class) return 0D; if (returnType == float.class) return 0F; if (returnType == short.class) return (short) 0; if (returnType == byte.class) return (byte) 0; if (returnType == char.class) return (char) 0; return null; } }
3. 使用示例
@RunWith(SpringRunner.class) @SpringBootTest() public class UserServiceTest { @SpyBean private UserService userService; @Test public void testIncreaseBalance() { // 一行代码完成所有方法批量Mock MockUtils.mockAllMethods(userService); // 后续测试逻辑 // ... } }
注意事项
- 如果只需Mock部分方法,可在工具类的过滤逻辑中添加自定义规则,比如按方法名、注解过滤
- 如果使用
@MockBean而非@SpyBean无需调用该工具:@MockBean生成的默认Mock对象,void方法默认doNothing,有返回值的方法默认返回对应类型的默认值 - final修饰的方法默认无法被Mockito Mock,需要额外配置Mockito inline mock maker才可支持
内容的提问来源于stack exchange,提问作者Nikitin
相关产品推荐
相关产品推荐

