文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

详解Spring云端微服务的组件测试

2024-12-02 05:45

关注

而不可否认的是,随着业界广泛采用云端微服务,我们在得益于处理多个可独立部署的组件的同时,需要提高微服务应用的测试级别,并按需增加测试策略的复杂性。下面,我将从使用者的角度出发,以一个Spring Cloud微服务为例,深入探究各种服务组件的相关测试。

服务

我们的Spring Boot微服务示例会具有如下特征:

我们将通过Java 11、Apache Maven、Docker、以及一组协作库,“尽早地”在CI/CD管道中,进行单独的服务测试,而无需实际部署或占用其他服务、数据库、甚至是完整的测试环境资源。同时,您可以通过链接--https://github.com/kmandalas/spring-cloud-component-tests,在GitHub上获取该示例的所有代码。

该示例中的“订单跟踪”微服务是由一个Spring Controller、Service和Repository所组成。它公开了两个端点:

  1. GET/api/orders/{trackingNumber}/status:它通过给定的跟踪号,执行数据库查询,来获取相关订单;然后调用FulfillmentService的内部服务,来确定交付的状态;进而让最终外部服务根据状态,调用位置服务来实现定位。这是一个带有有效的JWT、且受保护的API调用。
  2. GET/api/orders:通过查询数据库,以列出所有订单。这是一个受到额外授权限制的、且受保护的API调用。它仅适用于具有“back-office”角色的用户。

组件测试

OrderControllerTest.java类将针对API提供的多种方法,来封装组件测试。例如,我们可以选用包括:​​Maven插件​​、​​JUnit功能​​、​​Spring Boot测试切片​​和分类单元测试、集成测试、组件测试、合同测试等方法。当然,并非所有的测试类别都需要在CI/CD管道中被执行(或重新执行)。鉴于该示例过于简单,我强烈建议您实施适当的分类。

在​​/src/test/resources/application.yml​​中,我们针对属性的测试配置如下:

YAML

server:
port: 0

spring:
application:
name: order-service-test
cloud:
service-registry:
auto-registration:
enabled: false
loadbalancer:
ribbon:
enabled: false
config:
enabled: false
jpa:
show-sql: true

eureka:
client:
enabled: false
service-url:
registerWithEureka: false

okta:
oauth2:
issuer: https://kmandalas/oauth2/default

location-service:
  url: http://localhost:9999/v1/track/

在上述代码段所示中,我们禁用spring.cloud.config、eureka.client和spring.cloud.service-registry.auto-registration的原因在于,方便孤立地测试微服务。因此,既不会有Spring Cloud Config服务器在启动时,为OrderService的配置属性提供服务;也不会有Eureka服务器提供注册,并能够使用它来按需调用FulfillmentService的动态服务发现。

数据库

当出于测试目的而必须与数据库(关系型或NoSQL)集成时,我们通常有如下三种选择:

  1. 使用嵌入式或内存中(in-memory)方案,例如:H2,https://www.h2database.com/
  2. 使用一个能在测试期间可供访问的真实数据库
  3. 使用与生产数据库接近甚至相同的临时数据库

不同的选项所涉及到的测试资源,将会不尽相同。

可见,我们实际上只需要OrderControllerTest类上的@Testcontainers注释,以及如下的静态声明:

Java

@Container
static PostgreSQLContainer database = new PostgreSQLContainer("postgres:12")
.withDatabaseName("tutorial")
.withUsername("kmandalas")
.withPassword("dzone2022");

@DynamicPropertySource
static void setDatasourceProperties(DynamicPropertyRegistry propertyRegistry) {
propertyRegistry.add("spring.datasource.url", database::getJdbcUrl);
propertyRegistry.add("spring.datasource.password", database::getPassword);
propertyRegistry.add("spring.datasource.username", database::getUsername);
}

内部服务调用

我们将使用​​Spring Cloud OpenFeign​​来调用FulfillmentService,它是另一个“内部”的Spring Cloud微服务,可以被注册到Eureka上。在正常执行的情况下,后台的feign客户端能够通过名称定位目标服务实例,实现客户端的负载均衡(如果发现了多个实例的话)。

在我们的测试中,在没有Eureka(或者是​​Consul​​等其他发现机制)的情况下,我们需要通过如下两个方面,尽可能真实地模拟此类集成:

  1. 通过​​WireMock​​启动一个模拟服务器。该服务器能够根据URL的不同模式,来截获请求,并回复由我们提供的模拟响应。
  2. 使用@TestConfiguration来模拟各种FulfillmentService实例的发现,并将其指向WireMock服务器的URI。您可以通过链接--https://github.com/kmandalas/spring-cloud-component-tests/blob/50241126932fce3e9cfc6351291af5857f77806a/src/test/java/gr/kmandalas/dzone/OrderControllerTest.java#L55,查看到此类测试配置。

当然,您也可以使用​​Hoverfly​​作为嵌入式模拟服务器。在本示例里,我们通过如下依赖项设置,来引入WireMock:

XML

<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-contract-stub-runnerartifactId>
<scope>testscope>
 dependency>

通过spring-cloud-starter-contract-stub-runner,WireMock在Spring Boot应用测试套件中的引导被简化了许多,同时这对于​​契约测试​​(contract tests)也是非常实用的。请通过查看Spring Cloud Contract WireMock的链接--https://docs.spring.io/spring-cloud-contract/docs/current/reference/html/project-features.html#features-wiremock,了解更多相关信息。

有了上面的基础,我们只需要使用@AutoConfigureWireMock去注释测试类,并在测试资源目录下的​​JSON文件​​中定义各种WireMock映射即可。

外部服务调用

在集成的过程中,为了能够调用某些外部的(第三方)服务,我们仍然需要依赖有效的WireMock映射(毕竟能够提供的响应多多益善),以便在​​application.yml​​中定义测试URL资源。下面是一个简单的示例:

YAML

location-service:
  url: http://localhost:9999/v1/track/

我们在外部服务的URL端点路径处,提供了WireMock嵌入式服务器运行的主机和端口。端口号虽然不必经过硬编码,但是可以被定义为动态的,以便在CI/CD管道中并行运行多个组件测试,且不会发生端口冲突。

值得一提的是,WireMock不仅可以用于模拟来自RESTful服务的各种JSON响应,还可以模拟基于SOAP的Web服务的响应。

安全

正如前文提到的,Spring Cloud微服务基础设施通常能够合并出一个诸如Spring Cloud Gateway的API网关。据此,我们可以使用OAuth 2.0、JavaScript对象签名和加密(Object Signing and Encryption,JOSE)、以及JSON Web令牌标准的令牌中继模式,来处理用户的身份识别,授权应用程序查看他们的个人资料,以及访问网关后面的安全资源。通常,此类安全设置会由如下组件构成:

针对本测试示例,我们在单独测试Spring Boot微服务时,会采用​​Spring Security​​的SecurityMockMvcRequestPostProcessors。它将使我们能够在MockMvc调用期间,传递有效的JWT,定义权限(即用户角色),并在启用安全性的情况下,测试组件的行为。例如:

Java

mockMvc.perform(get("/api/orders/11212/status").with(jwt())).andExpect(status().isOk())

mockMvc.perform(get("/api/orders/").with(jwt().authorities(new 
SimpleGrantedAuthority("backoffice"))))
.andExpect(status().isOk());

小结

如今,对于成功的产品交付而言,开发人员是否能够在CI/CD管道中,以自动化的方式执行各类测试是至关重要的。希望上述讨论的有关Spring Cloud微服务组件测试的相关指南和注意事项,能够给您的实际项目交付提供帮助。

译者介绍

陈峻 (Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验;持续以博文、专题和译文等形式,分享前沿技术与新知;经常以线上、线下等方式,开展信息安全类培训与授课。

原文Component Tests for Spring Cloud Microservices,作者:Kyriakos Mandalas和Dimitris Stavroulakis


来源:51CTO内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯