当前位置:首页 > 科技  > 软件

深度揭秘JUnit5与Mockito的单元测试神秘面纱

来源: 责编: 时间:2024-01-02 09:31:59 313观看
导读在今天的学习中,我们将深入研究JUnit和Mockito,这是Java开发中最强大的单元测试工具之一。通过学习如何编写清晰、高效的单元测试,我们将揭开单元测试的神秘面纱,助力你在项目中写出更健壮的代码。提示: 今天的代码是在第

在今天的学习中,我们将深入研究JUnit和Mockito,这是Java开发中最强大的单元测试工具之一。通过学习如何编写清晰、高效的单元测试,我们将揭开单元测试的神秘面纱,助力你在项目中写出更健壮的代码。TVR28资讯网——每日最新资讯28at.com

提示: 今天的代码是在第九天代码的基础上进行开发,我们将为UserController中添加更多的单元测试方法,以展示JUnit和Mockito的强大功能。TVR28资讯网——每日最新资讯28at.com

核心知识介绍:

Unit 5 的主要特性和注解:@Test:标记方法作为测试方法。@BeforeEach / @AfterEach:分别表示在每个测试方法前后运行的方法。@BeforeAll / @AfterAll:分别表示在所有测试开始之前和所有测试结束之后只运行一次的方法。@DisplayName:为测试类或测试方法定义一个自定义的显示名称。@Nested:表示内部类,其成员方法可以作为嵌套的测试类进行分组。@Tag:为测试方法添加标签,可以用来过滤测试执行。@ExtendWith:用来注册自定义扩展,例如可以用来集成 Spring TestContext Framework。@Disabled:禁用某个测试方法或类。TVR28资讯网——每日最新资讯28at.com

JUnit 5 断言和假设:Assertions 类提供了一系列的静态方法来声明断言,如 assertEquals, assertTrue, assertAll 等。Assumptions 类提供了静态方法来声明测试的前提条件,如 assumeTrue。Mockito 的主要特性和注解:@Mock:创建一个模拟对象。@InjectMocks:自动注入模拟对象到被测试的类中。@Spy:创建一个真实对象的包装,可以模拟某些方法的行为。@Captor:创建一个参数捕获器,用于捕获方法调用的参数。TVR28资讯网——每日最新资讯28at.com

@TestMethodOrder 是一个类型级别的注解,用于指定测试类中测试方法的执行顺序。它需要与 MethodOrderer 接口的实现类一起使用,JUnit 提供了几种不同的方法排序器,如按名称、注解、随机等。TVR28资讯网——每日最新资讯28at.com

@Order 是一个方法级别的注解,用于指定测试方法的执行顺序。当测试类上使用了 @TestMethodOrder(OrderAnnotation.class) 注解时,你可以在每个测试方法上使用 @Order 来定义它们的执行顺序。TVR28资讯网——每日最新资讯28at.com

以下是一些常用的 MethodOrderer 实现:TVR28资讯网——每日最新资讯28at.com

OrderAnnotation:根据测试方法上的 @Order 注解来指定执行顺序。测试方法通过 @Order 注解的值(一个整数)来定义它们的执行顺序。Alphanumeric:按照测试方法名称的字母数字顺序执行。这个顺序首先考虑数字,然后是字母。MethodName:按照方法名称的字典顺序(即字符串顺序)执行。Random:每次执行时都按照随机顺序执行测试方法。这有助于发现由于测试方法间的依赖关系而产生的潜在问题。DisplayName:按照测试方法的显示名称(@DisplayName 注解指定的值)的字典顺序执行。TVR28资讯网——每日最新资讯28at.com

代码示例:

在今天的代码示例中,我们将在昨天的基础上进一步完善UserController的单元测试,使用JUnit和Mockito来验证控制器层的方法是否按照预期执行。TVR28资讯网——每日最新资讯28at.com

在 pom.xml 文件增加增加测试依赖TVR28资讯网——每日最新资讯28at.com

<dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-test</artifactId>      <version>3.1.6</version>      <!-- 排除 JUnit 4 -->      <exclusions>          <exclusion>              <groupId>org.junit.vintage</groupId>              <artifactId>junit-vintage-engine</artifactId>          </exclusion>      </exclusions>  </dependency>  <dependency>      <groupId>org.hamcrest</groupId>      <artifactId>hamcrest</artifactId>      <version>2.2</version>  </dependency>

UserControllerTest.javaTVR28资讯网——每日最新资讯28at.com

package com.icoderoad.springboot60days.day9.controller;import static org.hamcrest.Matchers.hasSize;import static org.hamcrest.Matchers.is;import static org.mockito.Mockito.*;import static org.mockito.ArgumentMatchers.any;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;import com.fasterxml.jackson.databind.ObjectMapper;import com.icoderoad.springboot60days.day9.entity.User;import com.icoderoad.springboot60days.day9.service.UserService;import org.junit.jupiter.api.*;import org.junit.jupiter.api.extension.ExtendWith;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.junit.jupiter.MockitoExtension;import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;import org.springframework.http.MediaType;import org.springframework.test.web.servlet.MockMvc;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.mock.mockito.MockBean;import java.util.Arrays;import java.util.List;@ExtendWith(MockitoExtension.class)@WebMvcTest(UserController.class)@TestMethodOrder(MethodOrderer.OrderAnnotation.class)public class UserControllerTest {    @Autowired    private MockMvc mockMvc;    @MockBean    private UserService userService;    @Autowired    private ObjectMapper objectMapper;    private User user;    @BeforeEach    void setUp() {        user = new User();        user.setId(1L);        user.setUsername("Test User");        user.setEmail("test@example.com");    }   /**     * 验证UserController的getAllUsers方法正常获取所有用户信息。     */    @Test    @Order(4)    public void getAllUsersTest() throws Exception {        List<User> users = Arrays.asList(user);        when(userService.list()).thenReturn(users);        mockMvc.perform(get("/users"))                .andExpect(status().isOk())                .andExpect(jsonPath("$", hasSize(1)))                .andExpect(jsonPath("$[0].username", is(user.getUsername())));    }   /**     * 验证UserController的createUser方法正常创建用户。     */    @Test    @Order(1)    public void createUserTest() throws Exception {        when(userService.saveOrUpdate(any(User.class))).thenReturn(true);;        mockMvc.perform(post("/users")                        .contentType(MediaType.APPLICATION_JSON)                        .content(objectMapper.writeValueAsString(user)))                .andExpect(status().isOk());        verify(userService, times(1)).save(any(User.class));    }   /**     * 验证UserController的getUserById方法正常获取指定ID的用户信息。     */    @Test    @Order(2)    public void getUserByIdTest() throws Exception {        when(userService.getById(user.getId())).thenReturn(user);        mockMvc.perform(get("/users/{id}", user.getId()))                .andExpect(status().isOk())                .andExpect(jsonPath("$.username", is(user.getUsername())));    }          /**     * 验证UserController的updateUserById方法正常更新指定ID的用户信息。     */    @Test    @Order(3)    public void updateUserByIdTest() throws Exception {      when(userService.saveOrUpdate(any(User.class))).thenReturn(true);;        mockMvc.perform(put("/users/{id}", user.getId())                        .contentType(MediaType.APPLICATION_JSON)                        .content(objectMapper.writeValueAsString(user)))                .andExpect(status().isOk());        verify(userService, times(1)).updateById(any(User.class));    }          /**     * 验证UserController的deleteUserById方法正常删除指定ID的用户。     */    @Test    @Order(5)    public void deleteUserByIdTest() throws Exception {      when(userService.removeById(user.getId())).thenReturn(true);;        mockMvc.perform(delete("/users/{id}", user.getId()))                .andExpect(status().isOk());        verify(userService, times(1)).removeById(user.getId());    }}

当天学习知识总结:

在今天的学习中,我们深入研究了单元测试,并利用 Mockito 框架加强了测试的功能。通过学习如何编写JUnit5测试以及使用Mockito模拟依赖,我们揭开了单元测试的神秘面纱,为更健壮的代码打下了坚实的基础。TVR28资讯网——每日最新资讯28at.com

在代码示例中,我们创建了一个 UserControllerTest 类,使用了 Mockito 注解和特性。主要注解包括 @Mock 用于创建模拟对象,@InjectMocks 用于创建被测试类的实例并自动注入模拟对象,@Spy 用于创建 Spy 对象,@Captor 用于捕获方法参数,以及 @RunWith(MockitoJUnitRunner.class) 用于在 JUnit 测试中运行 Mockito 测试。TVR28资讯网——每日最新资讯28at.com

通过这些注解和特性,我们能够编写清晰、高效的单元测试,验证控制器层的各个方法的行为是否符合预期。其中,我们测试了获取所有用户、创建用户、获取指定ID用户、更新用户、删除用户等方法,以确保它们在不同情况下能够正确执行。TVR28资讯网——每日最新资讯28at.com

总体而言,通过今天的学习,我们不仅深入了解了单元测试的基本原理,还学会了如何在Spring Boot项目中使用JUnit5和Mockito框架进行测试,为后续更复杂的业务逻辑和代码改动提供了可靠的测试基础。在接下来的学习中,我们将继续TVR28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-55352-0.html深度揭秘JUnit5与Mockito的单元测试神秘面纱

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 17个有用的CLI命令,作为前端工程师,你需要知道一下

下一篇: 软件测试走向智能化,行业领导者贡献凸显

标签:
  • 热门焦点
  • 官方承诺:K60至尊版将会首批升级MIUI 15

    全新的MIUI 15今天也有了消息,在官宣了K60至尊版将会搭载天玑9200+处理器和独显芯片X7的同时,Redmi给出了官方承诺,K60至尊重大更新首批升级,会首批推送MIUI 15。也就是说虽然
  • Raft算法:保障分布式系统共识的稳健之道

    1. 什么是Raft算法?Raft 是英文”Reliable、Replicated、Redundant、And Fault-Tolerant”(“可靠、可复制、可冗余、可容错”)的首字母缩写。Raft算法是一种用于在分布式系统
  • 微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • 在线图片编辑器,支持PSD解析、AI抠图等

    自从我上次分享一个人开发仿造稿定设计的图片编辑器到现在,不知不觉已过去一年时间了,期间我经历了裁员失业、面试找工作碰壁,寒冬下一直没有很好地履行计划.....这些就放在日
  • JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 造车两年股价跌六成,小米的估值逻辑变了吗?

    如果从小米官宣造车后的首个交易日起持有小米集团的股票,那么截至2023年上半年最后一个交易日,投资者将浮亏59.16%,同区间的恒生科技指数跌幅为52.78%
  • 三星Galaxy Z Fold5官方渲染图曝光:13.4mm折叠厚度依旧感人

    据官方此前宣布,三星将于7月26日在韩国首尔举办Unpacked活动,届时将带来带来包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy Z Flip 5、
  • SN570 NVMe SSD固态硬盘 价格与性能兼具

    SN570 NVMe SSD固态硬盘是西部数据发布的最新一代WD Blue系列的固态硬盘,不仅闪存技术更为精进,性能也得到了进一步的跃升。WD Blue SN570 NVMe SSD的包装外
  • 英特尔Xe HPG游戏显卡:拥有512EU,单风扇版本

    据10 月 30 日外媒 TheVerge 消息报道,英特尔 Xe HPG Arc Alchemist 的正面实被曝光,不仅拥有 512 EU 版显卡,还拥有 128EU 的单风扇版本。另外,这款显卡 PCB
Top