常用微服务框架的UT方案 |Java 开发实战

本文涉及的产品
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 经过前面几次文章的分享的UT的相关知识,相信应该对UT的好处和基本使用已经有了了解。今天接着分享UT相关最后一测文章,希望对大家在UT的学习中有一点点的帮助。

Spring集成测试


有时候我们需要在跑起来的Spring环境中验证,Spring 框架提供了一个专门的测试模块(spring-test),用于应用程序的集成测试。


在 Spring Boot 中,你可以通过spring-boot-starter-test启动器快速开启和使用它。

这时首先就有了Spring容器运行环境,就可以模拟浏览器调用等操作

引入测试坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.19.0</version>
    <scope>test</scope>
</dependency>

为了与生产环境配置区分开,一般都是配置多个配置文件,这样不同场景就能使用不同的配置文件


比如划分成-prod为生产环境,-dev为开发环境


新建一个application-test.yml

server:
  port: 8088 
spring:
  application:
    name: hello-service-for-test

controller类,也就是被测对象

@RestController
public class HelloController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello() throws Exception {
        return "Hello World";
    }
}


测试方案一


通过TestRestTemplate模拟调用Rest接口

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
class HelloControllerTest {
    @Autowired
    private TestRestTemplate restTemplate;
    @Value("${spring.application.name}")
    private String appName;
    @BeforeEach
    void setUp() {
        assertThat(appName).isEqualTo("hello-service-for-test");
    }
    @Test
    void testHello() throws Exception {
        String response = restTemplate.getForObject("/hello", String.class);
        assertThat(response).isEqualTo("Hello World");
    }
}


测试方案二


通过MockMvc来调用Rest接口

@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
class HelloControllerTest {
    @Autowired
    private HelloController helloController;
    @Autowired
    private MockMvc mockMvc;
    @Value("${spring.application.name}")
    private String appName;
    @BeforeEach
    void setUp() {
        assertThat(appName).isEqualTo("hello-service-for-test");
    }
    @Test
    void testHello() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
                .andDo(MockMvcResultHandlers.print())
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().string("Hello World"));
    }
}

方案一会启动Spring容器,相对更符合我们测试思路,建议选用此方案测试


方案二不会启动内置的容器,所以耗时相对少一点


与Spring类似dropwizard也有一套测试方案,可以提供Jetty容器来做集成测试


Dropwizard集成测试


引入maven坐标

<dependency>
  <groupId>io.dropwizard</groupId>
  <artifactId>dropwizard-testing</artifactId>
  <version>2.0.21</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter</artifactId>
  <version>5.6.2</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.assertj</groupId>
  <artifactId>assertj-core</artifactId>
  <version>3.19.0</version>
  <scope>test</scope>
</dependency>

被测试资源类

@Path("/ping")
@Service
public class PingResource {
    @GET
    public String ping() {
        return "pong";
    }
}


测试方案一


不启动Jetty容器,通过ResourceExtension扩展测试

@ExtendWith(DropwizardExtensionsSupport.class)
class PingResourceTest {
    private static final ResourceExtension EXT = ResourceExtension.builder()
            .addResource(new PingResource())
            .build();
    @Test
    void should_get_pong_when_send_ping() {
        String response = EXT.target("/ping").request().get(String.class);
        assertThat(response).isEqualTo("pong");
    }
}


测试方案二


通过启动Jetty容器测试,为了避免项目中的循环依赖关系或加快测试运行速度,可以通过将JAX-RS资源编写为测试DropwizardClientExtension来测试HTTP客户端代码,并启动和停止包含测试的简单Dropwizard应用程序。


@ExtendWith(DropwizardExtensionsSupport.class)
class PingResourceTest3 {
    private static final DropwizardClientExtension EXT = new DropwizardClientExtension(new PingResource());
    @Test
    void should_get_pong_when_send_ping() throws IOException {
        URL url = new URL(EXT.baseUri() + "/ping");
        System.out.println(url.toString());
        String response = new BufferedReader(new InputStreamReader(url.openStream())).readLine();
        assertThat(response).isEqualTo("pong");
    }
}
复制代码


测试方案三


通过指定yml配置文件,Jersey HTTP client调用Rest接口, 返回的客户端可以在测试之间重用


在JUnit5测试类中添加DropwizardExtensionsSupport注释和DropwizardAppExtension扩展名将在运行任何测试之前启动应用程序

并在测试完成后再次停止运行(大致等同于使用@BeforeAll@AfterAll

DropwizardAppExtension也暴露了应用程序的ConfigurationEnvironment并且应用程序对象本身,使这些可以通过测试进行查询。


新增配置文件\src\test\resources\hello.yml

server:
  type: simple
  rootPath: '/api/*'
  applicationContextPath: /
  connector:
    type: http
    port: 9090
复制代码

测试:

@ExtendWith(DropwizardExtensionsSupport.class)
class PingResourceTest2 {
    private static DropwizardAppExtension<HelloWorldServiceConfiguration> EXT = new DropwizardAppExtension<>(
            HelloWorldServiceApp.class,
            ResourceHelpers.resourceFilePath("hello.yml")
    );
    @Test
    void should_get_pong_when_send_ping() {
        Client client = EXT.client();
        String response = client.target(
                String.format("http://localhost:%d/api/ping", EXT.getLocalPort()))
                .request()
                .get(String.class);
        assertThat(response).isEqualTo("pong");
    }
}


目录
相关文章
|
1月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
1月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
1月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
Spring Boot 3.x 微服务架构实战指南
|
1月前
|
存储 安全 Java
《数据之美》:Java集合框架全景解析
Java集合框架是数据管理的核心工具,涵盖List、Set、Map等体系,提供丰富接口与实现类,支持高效的数据操作与算法处理。
|
1月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
117 8
|
1月前
|
存储 算法 安全
Java集合框架:理解类型多样性与限制
总之,在 Java 题材中正确地应对多样化与约束条件要求开发人员深入理解面向对象原则、范式编程思想以及JVM工作机理等核心知识点。通过精心设计与周密规划能够有效地利用 Java 高级特征打造出既健壮又灵活易维护系统软件产品。
71 7
|
2月前
|
监控 Java 数据库
从零学 Dropwizard:手把手搭轻量 Java 微服务,告别 Spring 臃肿
Dropwizard 整合 Jetty、Jersey 等成熟组件,开箱即用,无需复杂配置。轻量高效,启动快,资源占用少,内置监控、健康检查与安全防护,搭配 Docker 部署便捷,是构建生产级 Java 微服务的极简利器。
270 2
|
2月前
|
监控 Kubernetes Java
使用 New Relic APM 和 Kubernetes Metrics 监控 EKS 上的 Java 微服务
在阿里云AKS上运行Java微服务常遇性能瓶颈与OOMKilled等问题。本文教你通过New Relic实现集群与JVM双层监控,集成Helm部署、JVM代理注入、GC调优及告警仪表盘,打通从节点资源到应用内存的全链路观测,提升排障效率,保障服务稳定。
186 1
|
2月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
|
2月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。

热门文章

最新文章