如何进行微服务的集成测试

集成测试的概念

说到集成测试,相信每个测试工程师并不陌生,它不是一个崭新的概念,通过维基百科定义可以知道它在传统软件测试中的含义。

Integration testing (sometimes called integration and testing, abbreviated I&T) is the phase in software testing in which individual software modules are combined and tested as a group. Integration testing is conducted to evaluate the compliance of a system or component with specified functional requirements.

即,集成测试(有时称为集成和测试,简称 I&T)是软件测试中的阶段,在该阶段中,将各个单独开发的软件模块组合在一起并进行整体测试,以便评估系统或组件是否符合指定的功能要求。

微服务架构下也需要集成测试,需要针对不同服务的不同方法之间的通信情况进行相关测试。因为在对微服务进行单元测试时,单元测试用例只会验证被测单元的内部逻辑,并不验证其依赖的模块。即使对于服务 A 和服务 B 的单元测试分别通过,并不能说明服务 A 和服务 B 的交互是正常的。

对于微服务架构来说,集成测试通常关注于验证那些与外部组件(例如数据存储或其他微服务)通信的子系统或模块。目标是验证这些子系统或模块是否可以正确地与外部组件进行通信,而不是测试外部组件是否正常工作。因此,微服务架构下的集成测试,应该验证要集成的子系统之间与外部组件之间的基本通信路径,包括正确路径和错误路径。

微服务架构下的集成测试

如上图所示,网关组件层(Gateways+Http Client+External Service)包含了访问外部服务的逻辑,通常包含一个 HTTP/S 的客户端,客户端会连接到系统中另一个微服务或外部服务。数据持久层(Date Mappers/ORM)用于连接外部数据存储。

即,微服务架构下的集成测试主要包括两部分:

网关组件层, 微服务的组件与外部服务的通信路径;

数据持久层, 数据库访问模块与外部数据库的交互。

这里请注意,因为需要测试微服务下子系统之间的通信和外部服务的通信是否正确,所以理想情况下不应该对外部组件使用测试替身(Test Double)。

下面我们逐一来看这两部分是如何进行集成测试的:

(1)网关组件层集成测试

假设有个登录服务,该服务需要知道当前时间,而时间是由一个外部的时间服务提供的。当向 /api/json/cet/now 发出 GET 请求时,状态码为 200,并返回如下完整的时间信息。

{ 
$id: "1", 
currentDateTime: "2020-07-29T02:11+02:00", 
utcOffset: "02:00:00", 
isDayLightSavingsTime: true, 
dayOfTheWeek: "Wednesday", 
timeZoneName: "Central Europe Standard Time", 
currentFileTime: 132404622740972830, 
ordinalDate: "2020-211", 
serviceResponse: null, 
}

 如果访问的 URL 错误,比如向 /api/json111/cet/now发出 GET 请求时,状态码为 404,返回如下错误提示。

一般来说,集成测试会负责检验与外部服务的连接以及交互协议相关的问题,如 HTTP header 的缺失、SSL 处理的异常,或者请求/响应的不匹配。所有的错误处理逻辑都需要在测试中被覆盖,以确保所使用的服务和协议客户端在特殊情况下能够按预期进行响应。

(2)数据持久层集成测试

数据持久层的集成测试则要复杂一些,因为结果会被保存在存储系统上并被持久化,每次测试的执行都可能因为更改了数据而对后续测试的执行产生影响。这意味着,两次测试之间并非完全独立,因为它们操作了共同的数据。

绝大多数情况下,应该保证两次测试之间的外部因素也是相互独立的。因为这样的错误(测试数据的修改而导致的测试执行失败)出现后往往很难意识到,进而影响排查进度。

为了保障两次测试的独立性,持久层集成测试的常见步骤是:

  1. 在执行任意测试前,先回退数据库到一个已知且可预测的状态,这需要清理/回滚之前对数据库的修改;

  2. 通过插入对测试来说已知且预期中的数据来重建数据库;

  3. 进行相关的测试;

  4. 循环上述这个过程。

常见问题及解决策略

然而,有很多时候外部服务不可用(服务尚未开发完成、服务有 block 级别的缺陷未修复),或其异常行为(如外部组件的超时、响应变慢等)很难去验证。外部组件不能使用测试替身,外部服务又不可用或异常场景难构造,看似无解,实际上都是有替代方案的。

服务不可用

针对服务不可用的情况,微服务虚拟化技术可以完美解决这种问题,它是避免与其他服务通信时出现意外的必要工具,在具有大量依赖项的企业环境中工作的时候更是如此。它可以用于在测试阶段消除对第三方服务的依赖,测试应用程序在遇到延迟或其他网络问题时的行为。它通过创建代理服务实现对依赖服务的模拟,特别适合测试服务之间的通信。常见的工具有 Wiremock、Hoverfly、Mountebank 等。

以 Wiremock 为例,如下代码的效果是:当相对 URL 完全匹配 /api/json/cet/now 时,将返回状态 200,响应的主体类似于  /api/json/cet/now的返回值,Content-Type Header 的值为 text/plain。否则,当相对 URL 错误,比如访问 /api/json111/cet/now 时,则返回 404 的错误。

@Test 
public void exactUrlOnly() { stubFor(get(urlEqualTo("/api/json/cet/now")) .willReturn(aResponse() .withHeader("Content-Type", "text/plain") .withBody(equalToJson("{ $id: \"1\", currentDateTime: \"2020-07-29T02:11+02:00\", utcOffset: \"02:00:00\", isDayLightSavingsTime: true, dayOfTheWeek: \"Wednesday\", timeZoneName: \"Central Europe Standard Time\", currentFileTime: 132404622740972830, ordinalDate: \"2020-211\", serviceResponse: null, }")))); assertThat(testClient.get("/api/json/cet/now").statusCode(), is(200)); assertThat(testClient.get("/api/json111/cet/now").statusCode(), is(404)); 
}

服务超时&响应慢难构造

如果使用真实服务测试,服务超时或响应慢等情况需要特殊构造下,这时候借助各种工具会比较方便,比如常见的软件有 Fiddler、Dummynet、Clumsy 等。

Wiremock 也支持延迟的功能,比如使用 withFixedDelay() 可以实现固定延迟的效果:

stubFor(get(urlEqualTo("/api/json/cet/now")).willReturn( aResponse() .withStatus(200) .withFixedDelay(2000)));

使用 withLogNormalRandomDelay() 可以实现随机延迟效果:

stubFor(get(urlEqualTo("/api/json/cet/now")).willReturn( aResponse() .withStatus(200) .withLogNormalRandomDelay(90, 0.1)));

数据初始化和构造的成本高

上述对数据持久层集成测试的方法虽然通用,但是将数据库进行初始化需要编写大量的样例代码,插入预期的数据也需要编写大量的数据库操作语句。面对这个问题,可以使用一些现成的持久化测试框架来改善测试体验,常见的持久化测试框架有 NoSQLUnit、DBUnit 等。

DBUnit 的设计理念就是在测试之前,先备份好数据库,再给对象数据库植入需要准备的数据,在测试完毕后,再读入备份数据库,初始化到测试前的状态。DBUnit 可以在测试用例的生命周期内来对数据库的操作结果进行比较。DBUnit 支持的数据库有 db2、h2、mssql、mysql、oralce、postgresql 等。

NoSQLUnit 是用 DBUnit 类似的方式来编写 NoSQL 数据库的测试。支持多种 NoSQL 数据库,包括 HBase、MongoDB、Redis、ElasticSearch、Vault、Neo4j 等。

总结

本节课讲解了微服务架构下的集成测试定义,接着讲解了微服务下的集成测试的两个方面:网关组件层集成测试和数据持久层集成测试。

在网关组件层集成测试中,通过服务虚拟化技术来实现对外部服务能力的模拟,通过模拟网络异常情况来构造外部服务超时、响应慢的情况。

在数据持久层集成测试中,通过持久化测试框架可以避免常规持久化测试时编写大量代码和大量 SQL 语句的情况。

当然,如上框架和工具的威力不限于此,文中只给出了关键的示例信息,你可以根据需求或兴趣自行探索学习。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

在这里插入图片描述

软件测试面试小程序

被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!

涵盖以下这些面试题板块:

1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux

6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/84448.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Harbour.Space Scholarship Contest 2023-2024 (Div. 1 + Div. 2) A ~ D

比赛链接 A 正常枚举就行&#xff0c;从最后一位往前枚举&#xff0c;-1、-2、-3...这样 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std;typedef pair<int, int> PII; typedef long l…

初识 Redis

初识 Redis 1 认识NoSQL1.1 结构化与非结构化1.2 关联和非关联1.3 查询方式1.4. 事务1.5 总结 2 Redis 概述2.1 应用场景2.2 特性 3 Resis 全局命令4 Redis 基本数据类型4.1 String4.1.1 常用命令4.1.2 命令的时间复杂度4.1.3 使用场景 4.2 Hash4.2.1 常用命令4.2.2 命令的时间…

5G+智慧交通行业解决方案[46页PPT]

导读&#xff1a;原文《5G智慧交通行业解决方案[46页PPT]》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 喜欢文章&#xff0c;您可以点赞评论转发本文&#xff0c;…

二级MySQL(八)——删除表格数据

1、删除特定的数据记录 DELETE FROM tb_student WHERE studentName 黄涛; 删除前&#xff1a; 删除后&#xff1a; 2、带子查询的删除 DELETE FROM tb_student WHERE studentNo (SELECT studentNo FROM tb_student_copy WHERE studentName 孙新); 删除前&#xff1a; 删…

电商版面设计之优惠券设计

1、画一个矩形---最快的方法&#xff0c;提前写好 2、ALT复制矩形图层 3、提前把优惠券的文案准备好 4、改一下字体---72 5、字体改成12号字体 6、上面对齐选择第二个去做&#xff0c;最上方 7、后面那个就是门槛 8、用Alt复制4个 9、改字就行 10、看见不错的优惠劵设计可以参…

VMware ESXi 7.0 优化VMFSL磁盘占用与系统存储大小

文章目录 VMware ESXi 7.0 优化VMFSL磁盘占用与系统存储大小引言创建ESXi7.0可启动 U 盘结果检查VMware ESXi 7.0 优化VMFSL磁盘占用与系统存储大小 引言 本文讲述了在 J1900平台上安装ESXi7.0时减少 VMFSL 分区占用的说明, 通常这来说些主机内置的磁盘空间非常小, 采用默认安…

npm和yarn的区别?

文章目录 前言npm和yarn的作用和特点npm和yarn的安装的机制npm安装机制yarn安装机制检测包解析包获取包链接包构建包 总结后言 前言 这一期给大家讲解npm和yarn的一些区别 npm和yarn的作用和特点 包管理&#xff1a;npm 和 yarn 可以用于安装、更新和删除 JavaScript 包。它们提…

STM32 CAN 波特率计算分析

这里写目录标题 前言时钟分析时钟元到BIT 前言 CubeMX中配置CAN波特率的这个界面刚用的时候觉得非常难用&#xff0c;怎么都配置不到想要的波特率。接下来为大家做一下简单的分析。 时钟分析 STM32F4的CAN时钟来自APB1 在如下界面配置&#xff0c;最好配置为1个整一点的数。…

ChatGPT在医疗系统的应用探索动态

注意&#xff1a;本信息仅供参考&#xff0c;发布该内容旨在传递更多信息的目的&#xff0c;并不意味着赞同其观点或证实其说法。 生成式人工智能&#xff0c;如OpenAI开发的ChatGPT&#xff0c;被认为是可以颠覆医疗行业的工具。尽管该技术刚刚起步&#xff0c;但已有许多医…

在 macOS 中安装 TensorFlow 1g

tensorflow 需要多大空间 pip install tensorflow pip install tensorflow Looking in indexes: https://pypi.douban.com/simple/ Collecting tensorflowDownloading https://pypi.doubanio.com/packages/1a/c1/9c14df0625836af8ba6628585c6d3c3bf8f1e1101cafa2435eb28a7764…

设计模式--适配器模式(Adapter Pattern)

一、什么是适配器模式&#xff08;Adapter Pattern&#xff09; 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口。适配器模式主要用于解决不兼容接口之间的问题&#xff0c;使得原本…

深度学习10:Attention 机制

目录 Attention 的本质是什么 Attention 的3大优点 Attention 的原理 Attention 的 N 种类型 Attention 的本质是什么 Attention&#xff08;注意力&#xff09;机制如果浅层的理解&#xff0c;跟他的名字非常匹配。他的核心逻辑就是「从关注全部到关注重点」。 Attention…