接口测试 dubbo 接口测试技术

思寒_seveniruby · 2017年10月18日 · 最后由 CoraPeng 回复于 2021年11月04日 · 5276 次阅读

dubbo 是什么

dubbo 是阿里巴巴开源的一套 rpc 方案,以为理念很契合微服务,这几年很火,用户里面不凡京东,当当,去哪儿等大公司。
rpc 场景

dubbo 架构

官网也提供了一个很简单实用的 demo 来演示 dubbo 协议的使用,用起来的确很简单强大。

dubbo demo

可参考 http://dubbo.io/ 首页的例子已经很好了。

基于 telnet 的简单调试接口

任何一个 dubbo 服务都支持一个简单的 telent 交互。比如

telnet localhost 20880
>ls -l
> ls -l DemoService
> invoke DemoSerivce.sayHello("seveniruby")

这种方式只能用来简单验证接口的可用

传统的基于 xml 配置的 dubbo 的测试方法

首先创建一个 xml 文件放到 resources 下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="demo-consumer"/>
    <dubbo:registry address="dubbo://127.0.0.1:9090"/>
    <dubbo:reference id="demoService" interface="com.testerhome.tapi.dubbo.DemoService"/>
</beans>

通过使用一份 xml 配置文件进行测试

test("dubbo use registy xml"){
  val context = new ClassPathXmlApplicationContext("dubbo/consumer.xml")
  context.start()
  val demoService = context.getBean("demoService").asInstanceOf[DemoService]
  println(demoService.sayHello("seveniruby"))

  val req=new RequestModel()
  req.setName("james")
  req.getChild.setName("lily")
  println(TData.toJson(demoService.reqModel(req)))
}

基于 api 的 dubbo 测试方法

其实除了 xml 配置之外,官方也提供了一份直接通过 api 进行配置的方式,这个方式无疑是可编程比较灵活的

test("dubbo use registry"){
  // 当前应用配置
  val application = new ApplicationConfig
  application.setName("yyy")

  // 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接

  // 引用远程服务
  val reference = new ReferenceConfig[DemoService] // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
  reference.setApplication(application)
  reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
  reference.setInterface(classOf[DemoService])
  //reference.setUrl("dubbo://127.0.0.1:20881")
  reference.setTimeout(5000)

  // 和本地bean一样使用DemoService
  val DemoService = reference.get // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用
  System.out.println(DemoService.sayHello("seveniruby"))

  val req=new RequestModel()
  req.setName("james")
  req.getChild.setName("lily")
  System.out.println(TData.toJson(DemoService.reqModel(req)))
}

泛化调用

官方原话是

泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现。

这种情况适合自己打造接口测试框架使用。以上 2 个方式都需要依赖研发提供的 dubbo 接口的 jar 包,这无疑会增加项目的负担。
使用泛化可以不依赖任何研发提供的 jar 包,不过缺点也明显,仍然需要 jar 包或者其他的文档去分析 dubbo 接口的调用参数信息。
例子

test("泛化调用 by provider conf use map"){

  var reference = new ReferenceConfig[GenericService]() // 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
  reference.setGeneric(true) // 声明为泛化接口
  reference.setApplication(new ApplicationConfig("generic-provider"))
  //reference.setRegistry(registry)
  reference.setInterface("com.testerhome.tapi.dubbo.DemoService") // 弱类型接口名
  reference.setTimeout(5000)
  reference.setUrl(s"dubbo://127.0.0.1:20881")

  val genericService = reference.get
  val result = genericService.$invoke("sayHello", Array("java.lang.String"), Array("xxxx".asInstanceOf[AnyRef]))
  log.info(result)

  val childMap= mutable.Map[String, AnyRef]()
  childMap.put("name", "children")
  val map= mutable.Map[String, AnyRef]()
  map.put("name", "aaa")
  map.put("id", "11")
  map.put("child", childMap.asJava)

  val resModel=genericService.$invoke(
    "reqModel",
    Array("com.testerhome.tapi.dubbo.RequestModel"),
    Array(map.asJava.asInstanceOf[AnyRef]))
  log.info(resModel)
  log.info(TData.toJson(resModel))
}

虽然看起来还是依赖 jar 包,不过这个依赖就挺小了。如果你技术稍微 “猥琐” 点,就应该可以想到,只需要借助 asm 之类的字节码分析框架即可自动生成接口测试用例模板了。

dubbo 测试的技术关注点

  • dubbo 支持很多的协议,如果用的是 http 或者 hessian 协议,他们本身是文本的,可以直接使用 restassured 框架进行接口测试
  • dubbo 的 registry 保存了 dubbo 各种服务的注册信息,测试的时候可以直接用 registry,而不是直接连接到提供服务的 provider 上
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 9 条回复 时间 点赞

这个工具比较自动化,感觉方便点
https://github.com/everythingbest/dubbo-postman

对于使用 python 的哥们,使用 telnetlib 搭建 dubbo 测试框架非常好用,亲测有效!不过有个限制就是 dubbo 的接口必须都是接受 string 类型的请求参数!

如果是自定义类型参数,或者泛型的话,就不能用 telnet 了(因为 telnet 是完全模式用户操作,最后输入一定是 string 类型)。

回复

还有个问题请教下, 有没有更灵活方便完整的方法去获取 dubbo 的服务以及方法列表, 目前我都是直接写脚本 telnet 到服务端口获取或者从 zk 获取.

最近做 dubbo 接口测试, 发现 telnet 和泛化调用返回过来的结果字段不一致, 不知道是什么原因导致, 序列化吗?
还有个问题请教下, 像 dubbo 接口的测试用例应该如何设计, 从入参, 逻辑处理和返回这三个方面吗? 因为没有文档支持 , 感觉不好做 , 没有什么思路.

参数是对象,还不是需要依赖 jar 包?

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44
guoxd 回复

泛型一样可以

simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08

typo: telent

请问一下,有没有遇到过这种情况啊?

invoke disabled,不知道什么原因。网上也查不到😭

学习了,赞

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册