基于Dubbo的http自动测试工具分享

发表于:2018-1-08 10:37

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:xingoo    来源:博客园

  公司是采用微服务来做模块化的,各个模块之间采用dubbo通信。好处就不用提了,省略了之前模块间复杂的http访问。不过也遇到一些问题:
  测试需要配合写消费者的代码
  对于开发来说,倒是挺省劲。但是对于测试来说就有点麻烦了, 每次还要去写dubbo的消费程序,而且每次新增一个接口,都需要重新改写程序,费时费力。
  接口返回的结果无法定制
  由于我这边是做一些商品的推荐,每次结果的类型都是相同的,只是内部的算法不同。不过接口只是返回id,无法直观的判断商品相似程度或者用户的偏好程度,需要一个可视化的返回结果界面。
  于是在这种需求下,我设想了一个小程序,它可以满足下面的功能:
  1、测试可以根据测试需要,在界面自动选择请求的class和方法
  2、开发完成后,测试界面自动扫描出dubbo的提供者的class和对应的方法
  3、返回结果自动请求对应的图片和文字说明
  提前放一个效果图:
  1、扫描某个包下所有的类
  小程序开始的第一步就是需要扫描某个包下所有的dubbo实现类。
  由于工程是springboot,因此最终部署是在jar中。这时,就需要面临两个问题,如果是在开发工具中,如何获取包下的所有类;如果是在jar中,如何获取包下所有的类。
  首先通过classloader可以加载特定路径下的所有URL:
Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
//如果是jar,则采用JarURLConnection的方式连接,获得class文件
if("jar".equals(url.getProtocol())){
findClassesInJar(url,classes,pack);
}else{
findClassesInSrc(url,classes,pack);
}
}
  在工程中
  在工程中,class其实是以目录形式存放在本地的,直接按照file的方式遍历扫描class文件就行了:
public static void findClassesInSrc(URL url, Set<Class<?>> classes, String basePackage) throws UnsupportedEncodingException {
File dir = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
if (!dir.exists() || !dir.isDirectory()) {
return;
}
Arrays.stream(dir.listFiles())
.forEach(file -> {
String className = file.getName().substring(0, file.getName().length() - 6);
try {
classes.add(Thread.currentThread().getContextClassLoader().loadClass(basePackage + '.' + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
}
  在jar包中
  jar包是一种特殊的压缩包,java提供了JarFile类的entries方法,可以遍历jar中所有的文件。不过这里就没有目录或者文件的区别了,因为都是一个zip包中的资源而已。因此最后需要针对报名进行一下过滤:
public static void findClassesInJar(URL url,Set<Class<?>> classes,String basePackage) throws IOException, ClassNotFoundException {
//转换为JarURLConnection
JarURLConnection connection = (JarURLConnection) url.openConnection();
if (connection != null) {
JarFile jarFile = connection.getJarFile();
if (jarFile != null) {
//得到该jar文件下面的类实体
Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
while (jarEntryEnumeration.hasMoreElements()) {
JarEntry entry = jarEntryEnumeration.nextElement();
String jarEntryName = entry.getName();
//这里我们需要过滤不是class文件和不在basePack包名下的类
if (jarEntryName.contains(".class") && jarEntryName.replaceAll("/",".").startsWith(basePackage)) {
String className = jarEntryName
.substring(0, jarEntryName.lastIndexOf("."))
.replace("/", ".");
classes.add(Thread.currentThread().getContextClassLoader().loadClass(className));
}
}
}
}
}
  2、扫描某个class下所有的方法
  获得某个类的所有方法
  然后通过反射可以直接通过class的名字,拿到它的所有方法,这些方法里面包含了一些通用的方法,如wait,notify等,需要给过滤掉。
public static Set<String> NORMAL_METHODS = new HashSet<>(Arrays.asList("wait","equals","toString","hashCode","getClass","notify","notifyAll"));
public static List<Method> getMethod(String className){
try {
Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
Method[] methods = clazz.getMethods();
return Arrays.stream(methods)
.filter(method -> !NORMAL_METHODS.contains(method.getName()))
.collect(Collectors.toList());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return new ArrayList<>();
}
  这里需要注意,两个不同参数的方法,虽然名字相同,但是他们的parameterTypes是不同的。因此这里最好直接返回method,把name和parameterTypes一同作为结果返回。因为最终invoke的时候,还得通过参数类型把所有的参数都转换类型一下。

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
21/212>
《2023软件测试行业现状调查报告》独家发布~

精彩评论

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号