如何使用 MockServer 自动测试 Spring Boot API

标签: | 发表时间:2021-12-10 11:48 | 作者:
出处:https://medium.com

作为应用程序开发的一部分,系统集成是不可避免的。无论您的系统是一组 现代微服务还是遗留的单体系统,大多数系统逻辑都依赖于其他流程或数据源,以提供有意义的业务功能。集成将采用库函数调用或 REST API 调用的形式。与其他组件的接口通常令人头疼,尤其是在系统开发期间您的对应组件无法进行测试时。它是对接口逻辑的质量保证的约束。因此,在开发周期的后期会发现一些系统错误,并可能阻碍系统交付的进度。

长期以来,开发人员一直在为这个问题苦苦挣扎。过去,每个新开发项目都计划进行一定量的开发工作来构建模拟外部服务响应的存根,以便在没有这些依赖关系的情况下进行开发和测试。

例如,人们在接口组件中构建了一个适配器,用于从“离线”文件读取模拟数据响应。这样的适配器不是虚拟存根,开发是一项耗时且乏味的任务,因为它包含以专有格式解析消息并识别请求类型,然后查找并返回相应模拟响应的逻辑。这是银行业的常见做法,因为核心银行系统 AS/400 或大型机并不总是可用于通过银行门户进行测试。

具有用于测试的专用离线模式适配器的金融系统

如今,测试框架和模拟工具的普遍使用帮助我们更轻松地处理模拟。结合 Maven 等开发实用程序,大多数测试都可以自动化,从而大大加快开发和测试过程。在本文中,我将分享如何集成 MockServer并自动化 Java Spring Boot API 开发的单元测试和集成测试。

什么是模拟服务器?

您需要一个模拟 REST API 服务来验证整个开发周期中系统的功能和集成逻辑。但是,外部服务可能不可用,如果并行开发外部服务,通常会发生这种情况。 MockServer是一个有用的工具,它提供了一种模拟任何 REST API 服务的简单方法。它提供了开发人员友好的功能,例如 maven 插件和用于测试配置的注释。此外,它还支持 OpenAPI(又名 Swagger)定义、Java API 以及用于设置请求期望和模拟响应的 Javascript API。

它是一个独立的过程,它为一组期望的设置提供管理接口,即期望请求和模拟响应的映射。您可以调用其管理 REST API 或使用 MockServerClient(Java 或 JS 版本)来创建期望。

MockServer 请求流来自 (  https://www.mock-server.com/#what-is-mockserver )

与普通模拟响应类似,错误响应可以通过设置映射到错误响应的请求匹配器来模拟。

MockServer 请求流来自 (  https://www.mock-server.com/#what-is-mockserver )

下图显示了对客户服务的期望。为适应不同的测试场景,可以为正常情况配置模拟响应的映射,有 200 个状态和错误情况,例如 404 错误和 500 错误。

设定对客户服务的期望

配置了一组期望后,MockServer 会查找传入请求的一组期望,并在测试执行期间返回相应的模拟响应。

MockServer 根据配置的期望返回模拟响应

报价API

为了更好地说明这些概念,我将向您展示一个简单的保险报价 API 的实现。系统根据客户的要求生成报价建议。为了生成报价,业务规则在报价服务中编码,该服务协调和使用外部服务的 REST API——客户、产品和报价引擎。

报价API

下面的流程图显示了报价 API 的逻辑,它验证客户资料和产品规格,然后调用报价引擎 API。

报价服务逻辑流程

组件结构

除非你的系统超级简单,否则强烈建议定义一个 API 客户端来处理每个外部服务的 HTTP 通信和数据转换。这种设计有助于松耦合实现,使系统易于维护,以便将来进行故障排除和可能的修改。

使用 API 客户端与外部 API 集成

API 客户端

API 客户端负责与外部 REST API 的集成,例如 HTTP 协议请求和响应、转换错误状态代码以及数据转换。这是用于客户服务的 API 客户端的示例

Git 存储库

参考这个GitHub存储库( https://github.com/gavinklfong/spring-mock-demo.git)获取带有自动化测试实现的报价API的完整源代码

运行 maven command  mvn clean install,它将自动构建示例应用程序并使用 MockServer 运行测试。

运行 MockServer 进行单元测试

MockServer 支持许多选项来运行服务器,例如 Java API、JUnit 扩展、Docker 容器等。在这个例子中,我们使用 Java 注释运行 MockServer @MockServerTest进行单元测试。

您需要在 Maven pom.xml 中包含以下依赖项设置。

<dependency>     
<groupId>org.mock-server</groupId>
<artifactId>mockserver-spring-test-listener</artifactId>
<version>5.11.1</version>
</dependency>

在执行单元测试用例时,注释会在可用端口上启动 MockServer。MockServerClient 将自动注入测试类,因此您可以在测试执行之前向 MockServer 发送指令以设置模拟响应。每个测试用例都应该有自己的一组模拟响应配置,因为 MockServer 在每个测试用例执行之前被重置。

使用 OpenAPI 模拟期望设置

接下来,让我们演示如何使用 OpenAPI 定义(又名 Swagger)配置期望。OpenAPI 定义的支持改变了游戏规则,因为使用 OpenAPI 规范是 REST API 开发的常见做法。大多数服务提供商将其用作其 API 服务的接口规范。利用 OpenAPI 规范作为模拟响应设置可以为您节省大量的测试用例开发工作。

模拟响应可以作为 API 规范的一部分嵌入,您可以将其指定为示例数据。这是 GET /customers/{id}带有示例数据的端点的示例 OpenAPI 规范。

此示例代码将 OpenAPI 规范导入 MockServer,并指示 MockServer 为操作 ID 为“getCustomerById”的 API 端点设置 200 状态的模拟响应。您可以通过在方法调用中指定更多操作 id 来要求 MockServer 为多个 API 端点设置期望。

当调用客户 API 客户端以通过 id 获取客户时,它会将 API 请求提交给返回模拟响应的 MockServer。

使用 Java 代码模拟期望设置

或者,您可以使用 MockServerClient 的方法调用来开发模拟响应。代码简单明了,代码模式类似于 Mockito 的模拟。此示例展示了如何为 API 设置模拟响应以通过 id 检索产品 — [GET /products/{id}]

报价服务单元测试

虽然 Quotation 服务的单元测试不需要 MockServer,但不要忘记为 Quotation 服务开发测试。测试用例的实现可以简单地通过为所有 API 客户端注入模拟 bean 来完成。报价服务与系统逻辑验证的模拟交互。

集成测试怎么样?

一旦通过了所有单元测试,就可以将所有组件放在一起,并在集成测试中端到端地验证系统逻辑。系统边界是报价API,覆盖报价服务和所有API客户端,而所有外部服务都使用MockServer模拟。

集成测试设置

使用 Maven 生命周期运行集成测试

Maven 为集成测试的执行提供了一种便捷的方式。Maven 阶段称为预集成测试,用于在集成测试阶段执行测试用例之前初始化服务和应用程序。在集成测试结束时,maven 将运行post-integration-test阶段以关闭 Spring Boot 应用程序和 MockServer。

在预集成-测试阶段,我们首先使用 maven 插件build-helper-maven-plugin为 Spring Boot 应用程序和 MockServer 预留可用的网络端口,然后使用 maven 插件mockserver-maven-plugin和spring-boot-maven-plugin分别。

这种 Maven 配置对于测试自动化和 CI/CD 管道至关重要。

用于集成测试的 Maven 生命周期

网络端口预留的Maven插件设置

maven 插件会寻找 2 个可用的端口,并在pre-integration-test阶段设置为变量 spring-boot.http.portmock-server.http.port

MockServer 启动的 Maven 插件设置

下面的 maven 插件配置使用保留的端口号启动 MockServer。为了在启动时初始化 MockServer 中的所有期望,指定一个 java 类, <initializationClass>其中包含请求和模拟响应的映射列表。

初始化类实现了一个调用的接口 PluginExpectationInitializerinitializeExpectations()包含所有模拟响应设置。

Spring Boot 启动的 Maven 插件设置

为了指定端口号并覆盖 Spring Boot application.yml 中所有外部服务的 URL,该插件使用参数列表启动 Spring Boot。Spring Boot 应用程序将连接到 MockServer 以与外部服务(客户、产品和报价引擎)集成。

集成测试用例

随着 Spring Boot 应用程序和 MockServer 的启动和运行,测试用例将简单地运行一个 Web 客户端来触发对报价服务的 HTTP 请求以生成报价并验证结果。

最后的想法

无论您是构建大型企业系统还是小型服务, REST API 集成都是大多数系统架构中的常见模式。因此,REST API 模拟服务器已成为验证和质量保证的重要组成部分。

MockServer 是 Java Spring Boot API 开发的最佳选择,它是一个强大的工具,它为自动化测试用例设置提供了许多选项,例如 Java API、JUnit 扩展、Spring 测试执行侦听器、Docker 等。 模拟数据配置简单明了,你可以像 Mockito 风格的模拟那样做,也可以简单地使用 OpenAPI 规范。

它与 Maven 无缝协作,使得创建自动化管道以使用 MockServer 运行单元测试和集成测试变得更加容易。

相关 [mockserver 测试 spring] 推荐:

如何使用 MockServer 自动测试 Spring Boot API

- -
作为应用程序开发的一部分,系统集成是不可避免的. 无论您的系统是一组 现代微服务还是遗留的单体系统,大多数系统逻辑都依赖于其他流程或数据源,以提供有意义的业务功能. 集成将采用库函数调用或 REST API 调用的形式. 与其他组件的接口通常令人头疼,尤其是在系统开发期间您的对应组件无法进行测试时.

Spring与junit测试

- - CSDN博客Web前端推荐文章
1.我们知道无论在J2SE还是android中都有junit测试,利用junit能够帮助方便测试代码. 在之前的博客中我也写了一些J2SE的一些junit测试例子,今天对于Spring中junit小小的讨论一下. 这个Spring测试需要的jar包:. 2.Spring和Junit的关系图. 左边的采用传统的方式,即一般的J2SE的方式测试代码,这种情况会有些问题:.

Spring Cloud Contract 契约测试简介

- -
Spring Cloud Contract是一个项目,简单地说,就是帮助我们编写 消费者驱动的合同(CDC). 这确保了分布式系统中 Producer和 Consumer之间的契约——用于基于 HTTP 和基于消息的交互. 在这篇快速文章中,我们将探索通过 HTTP 交互为 Spring Cloud Contract 编写生产者和消费者端测试用例.

利用JUnit和Spring-test对SpringJDBC组件DAO层测试

- - ITeye博客
借着学习Druid连接池的机会,使用的Spring,将知识点联系起来,简单写了一个利用JUnit和Spring-test对SpringJDBC组件DAO层测试的Demo,分类归在Spring中吧. SpringJDBC组件是Spring提供的一个对底层JDBC的封装,扩展了更多更方便的接口,方便我们对数据库的操作.

Spring中DAO层接口的单元测试

- - 研发管理 - ITeye博客
单元测试在软件开发流程中有着举足轻重的作用,良好的单元测试的作用跟重要性不需多言. 基本上所有的java应用都会跟数据库打交道,DAO层接口的测试涉及到数据库测试数据的准备、维护、验证及清理. 单元测试应该要具有可重复性、独立性,所以单元测试的数据不应该污染数据库. 很多人在DAO层接口的单元测试中数据是自己手工插入的,第二次运行这个单测的时候就会得到duplicate key的错误,数据清理的过程中也是手工进行的,或者是通过try-catch-finally块进行清理,这自然是比较难以实现自动化测试的.

[翻译]使用Spring Boot进行单元测试

- - SegmentFault 最新的文章
原文地址: https://reflectoring.io/unit-.... 编写好的单元测试可以被看成一个很难掌握的艺术. 但好消息是支持单元测试的机制很容易学习. 本文给你提供在Spring Boot 应用程序中编写好的单元测试的机制,并且深入技术细节. 我们将带你学习如何以可测试的方式创建Spring Bean实例,然后讨论如何使用 Mockito和 AssertJ,这两个包在Spring Boot中都为了测试默认引用了.

项目中单元测试容易出现的普遍问题归纳(Junit/Spring/Spring-test/Dubbo/RocketMQ/JAVA)

- - 编程语言 - ITeye博客
   最近公司要求项目在使用maven构建的时候不能跳过test的生命周期,也就是通过mvn test命令需要将整个项目运行起来. 因为之前项目组的成员都是在eclipse中去执行的unit test,在maven对所有模块构建的都是直接-Dmaven.test.skip=true的方式直接跳过UT的.

利用h2database和easymock轻松不依赖环境单元测试(rose等spring环境万能)

- - 五四陈科学院-坚信科学,分享技术
以下内容由 [五四陈科学院]提供. 写java时间久了,慢慢就变得自信了,也可能是变得懒了,或者是项目进度的原因,test case越写越少,越来越不写了. 还有一个很大的原因是,DB环境不好搞,老是有垃圾数据,依赖的东西太多,有memcache、有别人的服务,等等等等,都是没有test case良好的理由.

Spring详解

- - CSDN博客架构设计推荐文章
Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目的是简化企业开发.. PersonDaoBean 是在应用内部创建及维护的. 所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的.

Spring定时

- - 行业应用 - ITeye博客
spring的定时任务配置分为三个步骤:. . . . . .