如何构建一个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接口测试)。
 1 public class AddMaterialListHelper extends SampleHelper<Result<List<FailData>>> {
 2 
 3     public static final String[] RANDOM_FIELD = {"materialCode","materialName"};
 4     
 5     @Override
 6     public Map<String, Object> readJsonFile(String jsonPath) {
 7         JsonParser parser = new JsonParser();
 8 
 9         try {
10             JsonObject json=(JsonObject) parser.parse(new FileReader(jsonPath));
11             Map<String, Object> values = new HashMap<String, Object>();
12             UtilsHelper.getInstance().getConnectionArgument(values, json);
13 
14             JsonObject args=json.get("Args").getAsJsonObject();
15             if (!args.get("data").isJsonNull()) {
16                 String jsonArray = args.get("data").getAsJsonArray().toString();
17                 //TODO
18                 Gson gson = new Gson();
19                 @SuppressWarnings("serial")
20                 List<MaterialInterfaceDTO> dtoList = gson.fromJson(jsonArray,
21                         new TypeToken<List<MaterialInterfaceDTO>>() {
22                         }.getType());
23                 RandomNum.setRandom(json , RANDOM_FIELD , dtoList);
24                 values.put("data", dtoList);
25             }
26 
27             if (!args.get("sourceSystem").isJsonNull()) {
28                 values.put("sourceSystem", new Integer(args.get("sourceSystem").getAsInt()));
29             }
30 
31             return values;
32 
33         } catch (JsonIOException e) {
34             e.printStackTrace();
35         } catch (JsonSyntaxException e) {
36             e.printStackTrace();
37         } catch (FileNotFoundException e) {
38             e.printStackTrace();
39         }
40         return null;
41     }
42 
43     @Override
44     public Result<List<FailData>> callRemoteMethod(Object object, Map<String, Object> values) {
45          MaterialInterfaceService service = (MaterialInterfaceService) object;
46          @SuppressWarnings("unchecked")
47         Result<List<FailData>> callResult = service.addMaterialList (
48                  (int) values.get("sourceSystem"),
49                  (List<MaterialInterfaceDTO>) values.get("data"));
50          return callResult;
51     }
52 }

 

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

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


     1 public class MaterialInterfaceDTO implements Serializable {
     2     private static final long serialVersionUID = -3725469669741557392L;
     3     private String materialCode;
     4     private String materialName;
     5     private Integer materialType;
     6     private Integer importFlag;
     7     private String sixNineCode;
     8     private Long expirationDate;
     9     private Long packingSpecification;
    10     private String basicUnit;
    11     private String minSaleUnit;
    12     private String basicUnitName;
    13     private String minSaleUnitName;
    14     private String materialImageUrl;
    15     private Integer transportFlag;
    16     private Integer sourceSystem;
    17     private String createName;
    18     private String updaterName;
    19 
    20     public MaterialInterfaceDTO() {
    21     }
    22 
    23     public String getMaterialCode() {
    24         return this.materialCode;
    25     }
    26 
    27     public void setMaterialCode(String materialCode) {
    28         this.materialCode = materialCode;
    29     }
    30 
    31     public String getMaterialName() {
    32         return this.materialName;
    33     }
    34 
    35     public void setMaterialName(String materialName) {
    36         this.materialName = materialName;
    37     }
    38 
    39     public Integer getMaterialType() {
    40         return this.materialType;
    41     }

     

 

  • 在init中通过java反射机制,获取json配置文件中设置好的辅助类的对象,然后在runTest中调用对应辅助类中
    callRemoteMethod,返回的结果解析后放到SampleResult的responeData,用来在jmeter中使用后置处理器进行
    结果判断。
      1 package com.utils.common;
      2 
      3 import com.alibaba.dubbo.config.ApplicationConfig;
      4 import com.alibaba.dubbo.config.ReferenceConfig;
      5 import com.google.gson.JsonObject;
      6 import com.google.gson.JsonParser;
      7 import org.apache.jmeter.config.Arguments;
      8 import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
      9 import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
     10 import org.apache.jmeter.samplers.SampleResult;
     11 
     12 import java.util.Map;
     13 
     14 public class RunMethodTest extends AbstractJavaSamplerClient {
     15     private static String JMX_PATH = null;
     16     private static String TAG = Thread.currentThread().getStackTrace()[1].getClassName();
     17     private SampleHelper helper = null;
     18     private Map<String, Object> values = null;
     19     private Map<String, Object> config = UtilsHelper.getInstance().getConfigProperties();
     20     private String ARGS_FILE;
     21     private Object object;
     22 
     23     public void setupTest(){
     24         //定义测试初始值,setupTest只在测试开始前使用
     25         System.out.println("setupTest");
     26     }
     27 
     28     public void init() {
     29         // 当前应用配置
     30         ApplicationConfig application = new ApplicationConfig();
     31         application.setName(TAG);
     32 
     33         // 获取具体参数配置路径
     34         if ("true".equals(config.get("DEBUG").toString())) {
     35             JMX_PATH = ARGS_FILE;
     36         } else {
     37             JMX_PATH = UtilsHelper.getInstance().getScriptPath(config.get("SCRIPT_HOME").toString(), ARGS_FILE);
     38         }
     39         Map<String, Object> helpArgs = UtilsHelper.getInstance().getHelpClassAndMethod(JMX_PATH);
     40         helper = (SampleHelper)UtilsHelper.getInstance().invokeStaticMethodByReflect(
     41                 (String) helpArgs.get("HELPCLASS"),
     42                 (String) helpArgs.get("HELPMETHOD")
     43         ) ;
     44 
     45         values = helper.readJsonFile(JMX_PATH);
     46 
     47         // 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接
     48         // 引用远程服务,配置dubbo服务版本、服务名称、url地址
     49         ReferenceConfig reference = new ReferenceConfig(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
     50         reference.setApplication(application);
     51         reference.setTimeout(20000);
     52         reference.setVersion(values.get("conn_version").toString());
     53         reference.setInterface(values.get("conn_service_name").toString());
     54         reference.setUrl(values.get("conn_url").toString());
     55 
     56         // 和本地bean一样使用xxxService
     57         object = reference.get(); // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用\
     58     }
     59 
     60     public SampleResult runTest(JavaSamplerContext arg0) {
     61         SampleResult sr = new SampleResult(); ;
     62         try {
     63             //获取参数
     64             ARGS_FILE = arg0.getParameter("ARGS_FILE");
     65 
     66             //dubbo初始化
     67             init();
     68 
     69             //jmeter结果对象
     70 //            sr.setSampleLabel(TAG);
     71             sr.sampleStart();
     72             sr.setSuccessful(true);
     73 
     74             String res = helper.handleResult(helper.callRemoteMethod(object, values));
     75 
     76             sr.sampleEnd(); // jmeter 结束统计响应时间标记
     77             if (res != null) {
     78                 JsonObject response = new JsonParser().parse(res).getAsJsonObject();
     79                 System.out.println("\n*************测试返回值****************\n");
     80                 System.out.print(response.toString()+"\n");
     81                 if (response.get("code").getAsInt() != 0) {
     82                     sr.setSuccessful(false);
     83                 }
     84                 sr.setResponseData(response.toString(), "UTF-8");
     85 //                if (null != response.get("data")) {
     86 //                    sr.setResponseData(response.get("data").toString(), "UTF-8");
     87 //                    System.out.print(response.get("data").toString()+"\n");
     88 //                } else if (null != response.get("result")) {
     89 //                    sr.setResponseData( response.get("result").toString(), "UTF-8");
     90 //                }
     91             } else {
     92                 System.out.print("handleResult return null\n");
     93             }
     94 
     95 
     96         } catch (Exception e) {
     97             e.printStackTrace();
     98             sr.setResponseCode("999");
     99             sr.setResponseMessage(e.getMessage());
    100             sr.setSuccessful(false);
    101         }
    102         return sr;
    103     }
    104 
    105     public Arguments getDefaultParameters(){
    106         //参数定义,显示在前台,也可以不定义
    107         Arguments params = new Arguments();
    108         params.addArgument("ARGS_FILE", "");
    109         return params;
    110     }
    111 
    112     public void teardownTest(JavaSamplerContext arg0){
    113         super.teardownTest(arg0);
    114     }
    115 
    116 }

     

版权声明:本文为habuge原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/habuge/p/10337134.html