如何构建一个Dubbo接口测试的通用框架(https://github.com/nitibu/jmeter-dubbo-test

从上面的流程我们可以看出,测试类大致的一个结构:

  • 使用json文件来构造测试数据
  • java程序只对json文件进行解析
  • 接口调用成功后,用json文件中的期望数据来对接口返回数据进行比对,判断调用是否成功

json文件的定义

{
  "Connection": {
    "URL": "101.219.255.73:50883",
    "SERVICE_NAME": "com.company.mdapi.sdk.material.export.MaterialApiService",
    "VERSION": "1.0.0",
    "METHOD": "queryUnboundListByPage",
    "HELPCLASS": "com.utils.common.helper.MaterialApiService.QueryUnboundListByPageHelper"
  },
  "Random": false,
  "Args": {
    "sourceSystem": 2,
    "querySourceSystem": null,
    "materialCode": "MD_S6006",
    "materialName": null,
    "materialType": null,
    "pkId": null,
    "shipperCode": "ZA01",
    "storageCenterCode": "HZA1",
    "pager": {
      "page": 1,
      "rows": 5,
      "totalCount": null,
      "pageOffset": null,
      "sort": "ID",
      "order": "ASC",
      "totalPage": null,
      "pageCode": 7,
      "startPageIndex": null,
      "endPageIndex": null,
      "previewPage": null,
      "nextPage": null
    }
  },
  "Verify": false
}

参数具体定义:

  • Connection:Dubbo服务的地址URL、服务名称SERVICE_NAME、版本号VERSION、远程接口调用的方法METHOD、
    数据转化处理的辅助类HELPCLASS。
  • Random:用来是能随机数设置,压力测试类似Add数据库操作时可以绕过数据库预设好的唯一性校验。
  • Args:调用接口时,传入的参数,这里提供的参数需要在辅助类中转换成接口参数,然后调用接口。
  • Verify:保留值,暂无使用

Java程序实现数据转换及接口调用

  • 辅助的Help类,需要继承SampleHelper类,同时实现其中的两个抽象方法readJsonFile和callRemoteMethod,
    分别用来读取json配置文件和调用远程方法(实际测试人员只需要实现这两个方法就可以进行Dubbo接口测试)。
 public class AddMaterialListHelper extends SampleHelper<Result<List<FailData>>> {

     public static final String[] RANDOM_FIELD = {"materialCode","materialName"};

     @Override
     public Map<String, Object> readJsonFile(String jsonPath) {
         JsonParser parser = new JsonParser();

         try {
             JsonObject json=(JsonObject) parser.parse(new FileReader(jsonPath));
             Map<String, Object> values = new HashMap<String, Object>();
             UtilsHelper.getInstance().getConnectionArgument(values, json);

             JsonObject args=json.get("Args").getAsJsonObject();
             if (!args.get("data").isJsonNull()) {
                 String jsonArray = args.get("data").getAsJsonArray().toString();
                 //TODO
                 Gson gson = new Gson();
                 @SuppressWarnings("serial")
                 List<MaterialInterfaceDTO> dtoList = gson.fromJson(jsonArray,
                         new TypeToken<List<MaterialInterfaceDTO>>() {
                         }.getType());
                 RandomNum.setRandom(json , RANDOM_FIELD , dtoList);
                 values.put("data", dtoList);
             }

             if (!args.get("sourceSystem").isJsonNull()) {
                 values.put("sourceSystem", new Integer(args.get("sourceSystem").getAsInt()));
             }

             return values;

         } catch (JsonIOException e) {
             e.printStackTrace();
         } catch (JsonSyntaxException e) {
             e.printStackTrace();
         } catch (FileNotFoundException e) {
             e.printStackTrace();
         }
         return null;
     }

     @Override
     public Result<List<FailData>> callRemoteMethod(Object object, Map<String, Object> values) {
          MaterialInterfaceService service = (MaterialInterfaceService) object;
          @SuppressWarnings("unchecked")
         Result<List<FailData>> callResult = service.addMaterialList (
                  (int) values.get("sourceSystem"),
                  (List<MaterialInterfaceDTO>) values.get("data"));
          return callResult;
     }
 }

  • 这里有个注意点,由于个博主所在的团队把接口参数封装成了一个可序列化的class类,所以需要进行数据转化,有些公司的
    接口参数直接传json字符串,那么只需要把json转换为字符串进行传参就可以。

    参数封装为序列化的class类:

     public class MaterialInterfaceDTO implements Serializable {
         private static final long serialVersionUID = -3725469669741557392L;
         private String materialCode;
         private String materialName;
         private Integer materialType;
         private Integer importFlag;
         private String sixNineCode;
         private Long expirationDate;
         private Long packingSpecification;
         private String basicUnit;
         private String minSaleUnit;
         private String basicUnitName;
         private String minSaleUnitName;
         private String materialImageUrl;
         private Integer transportFlag;
         private Integer sourceSystem;
         private String createName;
         private String updaterName;
    
         public MaterialInterfaceDTO() {
         }
    
         public String getMaterialCode() {
             return this.materialCode;
         }
    
         public void setMaterialCode(String materialCode) {
             this.materialCode = materialCode;
         }
    
         public String getMaterialName() {
             return this.materialName;
         }
    
         public void setMaterialName(String materialName) {
             this.materialName = materialName;
         }
    
         public Integer getMaterialType() {
             return this.materialType;
         }
  • 在init中通过java反射机制,获取json配置文件中设置好的辅助类的对象,然后在runTest中调用对应辅助类中
    callRemoteMethod,返回的结果解析后放到SampleResult的responeData,用来在jmeter中使用后置处理器进行
    结果判断。

     package com.utils.common;
    
     import com.alibaba.dubbo.config.ApplicationConfig;
     import com.alibaba.dubbo.config.ReferenceConfig;
     import com.google.gson.JsonObject;
     import com.google.gson.JsonParser;
     import org.apache.jmeter.config.Arguments;
     import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
     import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
     import org.apache.jmeter.samplers.SampleResult;
    
     import java.util.Map;
    
     public class RunMethodTest extends AbstractJavaSamplerClient {
         private static String JMX_PATH = null;
         private static String TAG = Thread.currentThread().getStackTrace()[1].getClassName();
         private SampleHelper helper = null;
         private Map<String, Object> values = null;
         private Map<String, Object> config = UtilsHelper.getInstance().getConfigProperties();
         private String ARGS_FILE;
         private Object object;
    
         public void setupTest(){
             //定义测试初始值,setupTest只在测试开始前使用
             System.out.println("setupTest");
         }
    
         public void init() {
             // 当前应用配置
             ApplicationConfig application = new ApplicationConfig();
             application.setName(TAG);
    
             // 获取具体参数配置路径
             if ("true".equals(config.get("DEBUG").toString())) {
                 JMX_PATH = ARGS_FILE;
             } else {
                 JMX_PATH = UtilsHelper.getInstance().getScriptPath(config.get("SCRIPT_HOME").toString(), ARGS_FILE);
             }
             Map<String, Object> helpArgs = UtilsHelper.getInstance().getHelpClassAndMethod(JMX_PATH);
             helper = (SampleHelper)UtilsHelper.getInstance().invokeStaticMethodByReflect(
                     (String) helpArgs.get("HELPCLASS"),
                     (String) helpArgs.get("HELPMETHOD")
             ) ;
    
             values = helper.readJsonFile(JMX_PATH);
    
             // 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接
             // 引用远程服务,配置dubbo服务版本、服务名称、url地址
             ReferenceConfig reference = new ReferenceConfig(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
             reference.setApplication(application);
             reference.setTimeout(20000);
             reference.setVersion(values.get("conn_version").toString());
             reference.setInterface(values.get("conn_service_name").toString());
             reference.setUrl(values.get("conn_url").toString());
    
             // 和本地bean一样使用xxxService
             object = reference.get(); // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用\
         }
    
         public SampleResult runTest(JavaSamplerContext arg0) {
             SampleResult sr = new SampleResult(); ;
             try {
                 //获取参数
                 ARGS_FILE = arg0.getParameter("ARGS_FILE");
    
                 //dubbo初始化
                 init();
    
                 //jmeter结果对象
     //            sr.setSampleLabel(TAG);
                 sr.sampleStart();
                 sr.setSuccessful(true);
    
                 String res = helper.handleResult(helper.callRemoteMethod(object, values));
    
                 sr.sampleEnd(); // jmeter 结束统计响应时间标记
                 if (res != null) {
                     JsonObject response = new JsonParser().parse(res).getAsJsonObject();
                     System.out.println("\n*************测试返回值****************\n");
                     System.out.print(response.toString()+"\n");
                     if (response.get("code").getAsInt() != 0) {
                         sr.setSuccessful(false);
                     }
                     sr.setResponseData(response.toString(), "UTF-8");
     //                if (null != response.get("data")) {
     //                    sr.setResponseData(response.get("data").toString(), "UTF-8");
     //                    System.out.print(response.get("data").toString()+"\n");
     //                } else if (null != response.get("result")) {
     //                    sr.setResponseData( response.get("result").toString(), "UTF-8");
     //                }
                 } else {
                     System.out.print("handleResult return null\n");
                 }
    
             } catch (Exception e) {
                 e.printStackTrace();
                 sr.setResponseCode("999");
                 sr.setResponseMessage(e.getMessage());
                 sr.setSuccessful(false);
             }
             return sr;
         }
    
         public Arguments getDefaultParameters(){
             //参数定义,显示在前台,也可以不定义
             Arguments params = new Arguments();
             params.addArgument("ARGS_FILE", "");
             return params;
         }
    
         public void teardownTest(JavaSamplerContext arg0){
             super.teardownTest(arg0);
         }
    
     }

【Jmeter测试】使用Java请求进行Dubbo接口的测试的更多相关文章

  1. jmeter中实现java请求实战日志

    view code public class JdbcInsert implements JavaSamplerClient { // 全局变量 PreparedStatement pstmt; Co ...

  2. 性能测试十一:jmeter进阶之java请求

    使用Java编写JDBC脚本对Mysql进行增删改查等操作的性能测试 使用Jmeter提供的脚本框架依赖的jar包(分别在jmeter目录下的lib和ext目录下) ApacheJMeter_core ...

  3. 想要测试Dubbo接口?测试的关键点在哪里?

    Dubbo接口如何测试? 这个dubbo如何测试,dubbo接口测试什么玩意儿?   RPC的有一个类型,叫Dubbo接口. 那这个接口如何测试?测试的关键点在哪里? 这个面试问题,我觉得大家可能就有 ...

  4. Java面向对象作业-用接口方式测试向下转型

    Java面向对象作业-用接口方式测试向下转型 根据视频的里实例 我们直接修改Test2测试方法: package com.java1234.chap03.sec13; public class Tes ...

  5. 【JMeter】JMeter完成一个java请求的压测

    先定义一下我说的remoteService:即远程调用服务,没有http的url.不对外提供或者对外提供有限的服务.具体视各公司的代码架构所定,比如有些公司为web工程,scf服务,db.scf即为服 ...

  6. jmeter之自定义java请求性能测试

    一.环境准备         1.新建一个java工程         2.导入jar包:ApacheJMeter_core.jar     ApacheJMeter_java.jar         ...

  7. 【转】JMeter完成一个java请求的压测

    JMeter完成java请求的压力测试详解以及问题总结 原文地址:http://www.cnblogs.com/zhaoxd07/p/4895224.html    作者:KK_Yolanda 这篇文 ...

  8. java反射调用dubbo接口

    需求:项目增加幂等 场景:1.三个项目:a .b.c2.a项目加幂等3.b项目dubbo调用项目a的时候超时没有获取返回结果,增加重试机制(非立即重试,3min or 5min 后重试)4.c项目是一 ...

  9. 性能测试十二:jmeter进阶之java请求参数化

    如项目中的ip.端口号之类的,都可以在此代码中定义 public Arguments getDefaultParameters() { // TODO Auto-generated method st ...

随机推荐

  1. MFC窗体程序中添加调试控制台

    在编写复杂程序的过程中,我们经常需要将一些信息输出到文件或者屏幕上.较控制台应用程序,MFC窗体程序要显得麻烦一些! 下面有2种方法来实现为MFC窗体程序添加调试控制台,方便程序员调试程序和了解当前程 ...

  2. Python cx_oracle自动化操作oracle数据库增删改查封装,优化返回查询数据

    # coding=utf-8 import cx_Oracle import os import json os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_C ...

  3. PAT——1021. 个位数统计

    给定一个k位整数N = dk-1*10k-1 + ... + d1*101 + d0 (0<=di<=9, i=0,...,k-1, dk-1>0),请编写程序统计每种不同的个位数字 ...

  4. STM32 以太网学习

    STM32进行以太网通信,需要  了解一下内容: 硬件层:MAC控制器  和  PHY 和 变压器 . 软件层:网络协议栈,例如:lwip协议栈,RL-TCPnet协议栈,FreeRTOS-TCP协议 ...

  5. 2017年秋招美团Java程序员开发,看我如何拿到offer

    本人是一名本科毕业非计算机专业的程序员,面了阿里,结果没过,最后面上了美团,热乎乎的面经,昨天面的美团,虽然面完了HR面,但是感觉希望不大,希望能走运拿到offer吧.记性不是太好,有一些问题没能记住 ...

  6. Kafka个人总结

    Kafka 应对场景:消息持久化.吞吐量是第一要求.状态由客户端维护.必须是分布式的.Kafka 认为 broker 不应该阻塞生产者,高效的磁盘顺序读写能够和网络 IO 一样快,同时依赖现代 OS ...

  7. Linux下ELK环境搭建

    一.准备工作 准备3台机器,这样才能完成分布式集群的实验,当然能有更多机器更好: 192.168.3.64(e1) 192.168.3.62  (e2) 192.168.3.63(e3) 角色划分: ...

  8. Kubernetes(一)--简介

    一.什么是kubernetes(K8s)? Kubernetes作为容器编排生态圈中重要一员,是Google大规模容器管理系统borg的开源版本实现,吸收借鉴了google过去十年间在生产环境上所学到 ...

  9. vue 复习(2)v-bind的应用 v-bind:classv-binf:style

    dasdclass与style绑定v-bind 1. 绑定HTML Class 对象语法 有些时候我们想动态的切换class的类名.在原生的js或jq中我们就要通过事件来动态的改变class类名,但在 ...

  10. 关于DP

    关于DP 似乎摸到了门槛呢,学着学着Dijkstra突然有了感觉. 我们遍历的时候会遍历整张图的每个点每条边,然后与已知的对比大小,如果比现在方案好,就放入数组 那么,DP岂不是同样的思想? 在背包问 ...