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

本文涉及的产品
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 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 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
19 5
|
1天前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
18 4
|
1天前
|
SQL Java API
|
1天前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
10 2
|
27天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
13天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
SQL Java 数据库连接
Java面试题日积月累(SSM框架面试题22道)
Java面试题日积月累(SSM框架面试题22道)
104 0
|
6月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
77 1
|
6月前
|
SQL Java 数据库连接
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
99 0
|
6月前
|
存储 安全 Java
Java面试题:请解释Java中的泛型集合框架?以及泛型的经典应用案例
Java面试题:请解释Java中的泛型集合框架?以及泛型的经典应用案例
75 0