如何改造JUnit5 MockitoExtension,将接口Mock替换为对应实现类?
改造JUnit5 MockitoExtension实现接口Mock绑定对应实现类
核心思路
MockitoExtension创建Mock的核心逻辑是通过MockAnnotationProcessor处理@Mock注解,我们可以自定义处理器替换默认实现,在创建Mock前先从你的静态注册表中查找接口对应的实现类,再用实现类生成Mock实例,完全兼容原有Mockito功能。
具体实现步骤
1. 自定义MockAnnotationProcessor
继承默认的DefaultMockAnnotationProcessor,重写createMock方法,增加接口到实现类的替换逻辑:
public class CustomMockAnnotationProcessor extends DefaultMockAnnotationProcessor { @Override public Object createMock(MockSettings mockSettings, AnnotatedElement annotatedElement, Type genericType, Annotation annotation) { Class<?> targetType = resolveRawType(genericType); // 仅处理接口类型,且注册表中有对应实现类的情况 if (targetType.isInterface()) { Class<?> implClass = YourStaticRegistry.getImplByInterface(targetType); if (implClass != null) { // 替换目标类型为实现类,保留原有Mock配置 return Mockito.mock(implClass, mockSettings); } } // 无匹配实现类时,走默认Mock创建逻辑 return super.createMock(mockSettings, annotatedElement, genericType, annotation); } // 解析泛型类型到原始类 private Class<?> resolveRawType(Type genericType) { if (genericType instanceof Class<?>) { return (Class<?>) genericType; } else if (genericType instanceof ParameterizedType) { return (Class<?>) ((ParameterizedType) genericType).getRawType(); } throw new IllegalArgumentException("不支持的类型: " + genericType); } }
2. 自定义AnnotationEngine
替换默认的IndependentAnnotationEngine,让它使用我们的自定义处理器:
public class CustomMockitoAnnotationEngine extends IndependentAnnotationEngine { @Override public void process(Class<?> testClass, Object testInstance, MockitoAnnotations.Mock mockAnnotation, Field field) { CustomMockAnnotationProcessor processor = new CustomMockAnnotationProcessor(); Object mock = processor.createMock( MockitoSettings.using().get(), field, field.getGenericType(), mockAnnotation ); // 注入Mock实例到测试类字段 MockitoAnnotations.openMocks(testInstance).injectMock(mock, field); } }
3. 自定义MockitoExtension
扩展原MockitoExtension,指定使用我们的自定义AnnotationEngine:
public class CustomMockitoExtension extends MockitoExtension { @Override protected AnnotationEngine createAnnotationEngine() { return new CustomMockitoAnnotationEngine(); } }
4. 在测试类中使用自定义扩展
替换原有@ExtendWith(MockitoExtension.class)为自定义扩展即可:
@ExtendWith(CustomMockitoExtension.class) public class FooServiceTest { @Mock private FooService fooService; // 此处实际生成的是FooServiceImpl类型的Mock实例 // 测试方法逻辑... }
关键注意事项
- 确保你的静态注册表
YourStaticRegistry能稳定根据接口类型返回对应实现类,处理好空值场景(无映射的接口仍走默认Mock逻辑)。 - 若需处理复杂泛型,要完善
resolveRawType方法的类型解析逻辑,避免转换异常。 - 该改造仅介入Mock创建的类型选择环节,不会影响Mockito的其他核心功能(如验证、Stubbing等)。
内容的提问来源于stack exchange,提问作者JeanValjean
相关产品推荐
相关产品推荐

