5.4 TestNG Dubbo 接口自动化测试
在使用 TestNG 进行 Dubbo 接口自动化测试之前,需要先创建一个新的 Maven 项目,关键信息填写如图 5-4 所示。
创建完成后,在 pom.xml 文件的<;name>;标签后输入以下粗体部分内容:
① TestNG:自动化测试框架 TestNG 的依赖。
② spring-boot-starter-web:作为 Web 开发的基础,这里需要使用其中的一些功能用于测试。
③ Dubbo:分布式微服务框架 Dubbo 的依赖。
④ curator-recipes:注册中心 ZooKeeper 框架的依赖。
⑤ Fastjson:用于将实体类转换为 JSON 字符串,相当于执行了序列化操作。
依赖 jar 包下载完成后,在工程(rpcinterfacetest)上用鼠标右击,从弹出的快捷菜单中选择「TestNG→ Convert to TestNG」选项,在工程中生成 testng.xml 文件。
Dubbo 接口自动化测试的方法有 4 种。
① 基于 XML:使用 XML 文件配置消费者。
② 基于 API:使用 Dubbo API 直接配置消费者。
③ 基于注解:使用注解和 properties 文件配置消费者。
④ 泛化调用:泛化调用主要用于消费者没有 API 接口的场景,这时不需要引入接口的 jar 包,直接通过 GenericService 接口来发起 Dubbo 接口调用,Dubbo 自动化测试框架也是基于泛化调用实现的。
上述方法中的消费者其实就是放置测试用例的工程。
5.4.1 基于 XML 方式
基于 XML、API 和注解的方式均需要依赖接口的 jar 包。从笔者的 GitHub 中下载接口的 jar 包,jar 包名为 mobilephoneservice.jar。下载后在工程(rpcinterfacetest)上用鼠标右击,从弹出的快捷菜单中选择「Build Path → Configure Build Path...」选项,显示如图 5-5 所示。
单击「Add External JARs...」选项,选择刚刚下载的「mobilephoneservice.jar」文件,然后单击「Apply and Close」按钮,完成 jar 包的导入。
为简明步骤,采用直接导入 jar 包的方式。在实际项目中,依赖 jar 包一般放在 Maven 私服。将 Eclipse 使用的 Maven 仓库地址配置为 Maven 私服地址。Maven 私服的使用已经超出本书的探讨范围,有兴趣的读者可以自行查阅相关资料。
1.通过注册中心调用 Dubbo 接口
在 src/test/resources 中创建名为 consumer 的 XML 文件,在 consumer.xml 中输入以下内容:
①dubbo:application 标签的 name 属性用于指定程序名称,服务提供者和服务消费者的名称不能设置成相同的。
②dubbo:registry 标签的 registry 属性代表配置注册中心,包括注册中心的类型、IP 地址和端口。
③dubbo:reference 标签的 id 属性用于后续的引用(稍后会介绍),interface 属性设置消费者需要使用的服务,version 属性设置服务版本。需要注意的是,version 如果不填或填错,会造成与服务提供者的接口版本号不一致,从而无法找到服务提供者。
在 src/test/java 中创建名为 com.lujiatao.rpcinterfacetest 的 Package 及名为 GetMobilePhoneTest 的 Class,在 GetMobilePhoneTest 中输入以下内容:
图 5-6
下面对上述运行结果进行说明。
① 在 init()方法中,传入 xml 文件作为参数,构建一个 IoC(Inversion of Control,控制反转)容器,并通过 start()方法启动,在 clear()方法中关闭。init()方法中还做了另一件事,就是通过 dubbo:reference 标签的 id 属性值获取服务。
② 在测试用例方法(testCase1—testCase4)中通过封装的 invokeGetMobilePhoneMethod()方法来调用接口中的方法,并对返回值进行断言。这里使用了 Fastjson 中的 toJSONString()方法将实体类转换成了 JSON 字符串。
这里不再演示 saveMobilePhone 的自动化测试用例编写,读者可以按照 getMobilePhone 的示例自行编写,编写方法是一样的。
2.通过直连方式调用 Dubbo 接口
前面是通过注册中心调用 Dubbo 接口的,其实可以绕过注册中心,直接连接服务提供者来调用 Dubbo 接口。直连的优点是只关心 Dubbo 本身的功能,更为纯粹。缺点是无法模拟真实服务消费者的调用,因为真实服务消费者是通过注册中心的订阅/发布策略来获取服务提供者,并进行 Dubbo 接口调用的。
用直连方式调用 Dubbo 接口很简单,删除 consumer.xml 中的 dubbo:registry 标签,并在 dubbo:reference 标签中配置直连地址即可,如下粗体部分内容所示:
5.4.2 基于 API 方式
API 与 XML 有一对一的关系,比如 ApplicationConfig.setName(「MyName」)对应<;dubbo:application name=「MyName」/>;。
本节只演示一条自动化测试用例(getMobilePhone 中的 Case 1)的编写,读者在学会方法后,可以自行将所有手工测试用例转化为自动化测试用例。
清空 GetMobilePhoneTest 中的内容,重新输入以下代码:
① 在 init()方法中通过 Dubbo API 设置程序名称、注册中心和接口,这里设置的项目和 5.4.1 节中的基本相同,只不过把 XML 换成了 API。
② 删了 clear()方法,因为这里不使用 IoC 读取 XML 文件,因此不需要关闭 ClassPathXmlApplicationContext 对象。
5.4.3 基于注解方式
注解方式比 XML 和 API 两种方式要复杂一些。
在 com.lujiatao.rpcinterfacetest Package 中创建名为 AnnotationClass 和 ConsumerConfiguration 的 Class,输入以下代码:
该类的作用充当了基于 XML 中 dubbo:reference 标签的角色,即提供服务引用。@Component 注解告诉 Spring 需要为该类创建 Bean,并指定了名称。而@Reference 注解代表引用服务提供者所提供的服务,并指定了版本号。
该类用作载入 Bean 扫描配置、Dubbo 扫描配置和 properties 文件配置。
在 src/test/resources 中创建名为 application.properties 的文件,在 application.properties 中输入以下内容:
该文件为配置文件,这里配置了程序名称和注册中心。
清空 GetMobilePhoneTest 中的内容,并重新输入以下代码:
5.4.4 泛化调用
泛化调用的核心在于使用 GenericService 接口,通过 GenericService 接口的 $invoke()方法调用目标 Dubbo 接口。$invoke()方法有 3 个参数,含义如下。
①String method:方法名。
②String[] parameterTypes:参数类型,这里的参数类型需要写全路径,比如「java.lang.String」。
③Object[] args:参数。
清空 GetMobilePhoneTest 中的内容,并重新输入以下代码:
保存所做的修改,在 testng.xml 上用鼠标右击,从弹出的快捷菜单中选择「Run As → TestNG Suite」选项,查看测试报告,如图 5-7 所示。
图 5-7
从测试报告中可以看出,测试用例执行失败了。单击「testCase1」选项,查看失败原因,如图 5-8 所示。
图 5-8
复制 expected 后面的方括号中的内容,如下所示:
① 返回的字段多了一个 class。为什么会这样呢?因为返回值是一个 MobilePhone 对象,当泛化调用采用 Map 方式表示该对象时,如果不加入 class 这个 Key,则无法判断该对象是哪个类的实例。
② 字段的顺序与预期结果不一致。
如何处理上面两个问题呢?
首先引入一个新的依赖 Gson,即在 pom.xml 文件的<;dependencies>;标签中加入以下依赖。
然后修改 GetMobilePhoneTest 中的代码,如下面粗体部分内容所示。
保存所做的修改,在「testng.xml」上用鼠标右击,从弹出的快捷菜单中选择「Run As → TestNG Suite」选项,查看测试报告,如图 5-9 所示,表示测试用例执行成功。
图 5-9