自定义注解返回mock数据
1. 如果配置mock测试为真,返回mock数据,为假,返回真实数据
2. 实现方式
可以每次在方法中判断,但是很麻烦,好多if判断
可以定义接口,多一个mock实现,在程序启动的时候,只加载mock实现类,真实实现类不加载(可以自定义类加载器或者使用spring bean加载过滤)
也可以使用AOP切面,判断是否mock看情况返回
其他实现方式暂时没有想法或者头绪
最后确定使用AOP简单快捷
3. 代码
自定义注解
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MockData {
@AliasFor("method")
String value() default "";
/**
* 是否开启mock数据返回
*/
boolean isOpen() default true;
/**
* 指定mock数据组装 <strong>无参</strong>方法
*/
@AliasFor("value")
String method() default "";
/**
* mock方法类,默认当前类
* class数组有且只能有一个class,该类最好使用spring bean管理
*/
Class<?>[] classFor() default {};
}
AOP 切面
@Slf4j
@Aspect
@Component
public class MockAspect {
@Value("${mockModal}")
private boolean mockModal;
@Autowired
private BeanFactory beanFactory;
/**
* mock数据切面方法
*
* @param joinPoint
* @param mockData
*/
@Around("within(@org.springframework.stereotype.Service *) && @annotation(mockData)")
public Object around(ProceedingJoinPoint joinPoint, MockData mockData) {
Object res = Res.fail("服务内部mock数据错误!");
try {
// 判断是否开启了 mock 数据返回
if (mockData.isOpen() && mockModal) {
// @AliasFor 是spring 特有注解,这里使用spring提供的工具类获取注解,要不然 value和method互替不会生效
mockData = AnnotationUtils.getAnnotation(mockData, MockData.class);
assert mockData != null;
Object bean;
Method[] methods;
if (mockData.classFor().length == 0) {
// 默认使用当前类
bean = beanFactory.getBean(joinPoint.getTarget().getClass());
methods = joinPoint.getTarget().getClass().getDeclaredMethods();
} else {
try {
bean = beanFactory.getBean(mockData.classFor()[0]);
} catch (NoSuchBeanDefinitionException e) {
log.warn("mock数据访问类不在spring bean工厂中改用反射方式...");
bean = mockData.classFor()[0].newInstance();
}
methods = mockData.classFor()[0].getDeclaredMethods();
}
// mock 注解指定的 mock方法名
String name = mockData.method();
Optional<Method> check = Arrays.stream(methods).filter(method -> method.getName().equals(name)).findFirst();
if (check.isPresent()) {
Method method = check.get();
method.setAccessible(true);
// 执行 mock 方法
res = method.invoke(bean);
}
} else {
res = joinPoint.proceed();
}
} catch (Throwable throwable) {
log.error("mock数据切面出错!", throwable);
}
return res;
}
}
使用:在实现类方法上使用,指定mock方法
@Override
@MockData("mockSearch")
public Res search(AddDTO dto) {...}
private Res mockSearch() {
return Res.ok("mock data");
}
其中 Res 是返回封装类,没有其他特殊作用。mockModal 是配置是否使用mock数据的配置项。

浙公网安备 33010602011771号