mybatis冒烟测试工具
日常中的开发工作,大部分都是增删改查,所以和SQL打交道的时候特别多,我在日常工作中,使用的最多的是mybatis和mysql,用的是spring boot框架,所以在改完代码之后,全量测试下SQL是否正确,就非常重要了。有时候单元测试没来得及写全,所以有一个简单的工具,可以做一下冒烟测试,也是非常有必要的,可以避免低级错误。
所以就萌生了一个想法,通过反射,获取系统中的所有的SQL,挨个执行一遍,简单测试下SQL是否报错。
1、说干就干
思路明确了,先去网上搜索下,有没有别人已经做过了。简单搜了下,确实有人做过,必须要传入dao文件的物理路径,然后解析文件,这明显不是我想要的效果。
-
通过spring boot拿所有的代理类,没有行的通,失败。
-
通过反射拿所有的类,需要硬编码所有的dao的名字,失败。
-
相继失败之后,研究了下mybatis原理,发现所有的代理类,都封装成了MapperFactoryBean,通过ApplicationContext拿所有的这个类,成功。
2、一些挫折
拿到了 MapperFactoryBean之后,却怎么也拿不到MapperProxy,MapperProxy是mybatis的代理类,本来想强制转换的,结果一直报com.sun.proxy.$80Proxy不能转换为MapperProxy,郁闷,必须转换下思路。
3、解决
反射执行方法,是method.invoke(obj,param); obj是不是不需要转换? 我的天,绕弯路了,根本不需要转换得到MapperProxy,直接就解决了,剩下的问题就比较简单了。
- 拿到dao类,反射得到所有的方法。
- 解析方法的参数,使用随机工具类,生成测试参数。
- 对于long类型的id,控制下范围。
- 对于string类型的,控制下长度,毕竟数据库里的varchar,一般都有最大长度。
4、代码
直接看代码吧:
@Test
public void testAllDao() throws Throwable {
//SpringContextUtil类就是实现ApplicationContextAware即可
Map<String, MapperFactoryBean> map = SpringContextUtil.getApplicationContext().getBeansOfType(org.mybatis.spring.mapper.MapperFactoryBean.class);
for (Map.Entry<String, MapperFactoryBean> entry : map.entrySet()) {
MapperFactoryBean mapperFactoryBean = entry.getValue();
Class clz2 = mapperFactoryBean.getMapperInterface();
Object object = mapperFactoryBean.getObject();
Method[] methods = clz2.getMethods();
for (Method method : methods) {
Class[] paramClz = method.getParameterTypes();
Object[] param = new Object[paramClz.length];
for (int i = 0; i < paramClz.length; i++) {
//newInstance自己实现,模拟测试数据。
param[i] = newInstance(paramClz[i]);
}
try {
method.invoke(object, param);
System.out.println("执行class " + clz2.getName() + " 方法 " + method.getName() + " 成功");
} catch (Exception e) {
System.out.println("执行class " + clz2.getName() + " 方法 " + method.getName() + " 异常");
e.printStackTrace();
}
}
}
System.out.println("执行结束。。。。。。。。。。。。");
}
4、小结
遇到问题不要慌,先网上搜,再看原理,遇到问题,都需要先假设犯了低级错误。同时我自己还维护了一个博客: https://www.epoooll.com/mybatis-test-sql/ ,里面会有我最新的文章。