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

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

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

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

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

核心知识介绍:

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

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

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

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

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

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

代码示例:

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

在 pom.xml 文件增加增加测试依赖TZb28资讯网——每日最新资讯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.javaTZb28资讯网——每日最新资讯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模拟依赖,我们揭开了单元测试的神秘面纱,为更健壮的代码打下了坚实的基础。TZb28资讯网——每日最新资讯28at.com

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

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

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

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

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

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

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

标签:
  • 热门焦点
  • 对标苹果的灵动岛 华为带来实况窗功能

    继苹果的灵动岛之后,华为也在今天正式推出了“实况窗”功能。据今天鸿蒙OS 4.0的现场演示显示,华为的实况窗可以更高效的展现出实时通知,比如锁屏上就能看到外卖、打车、银行
  • Redmi Buds 4开箱简评:才199还有降噪 可以无脑入

    在上个月举办的Redmi Note11T Pro系列新机发布会上,除了两款手机新品之外,Redmi还带来了两款TWS真无线蓝牙耳机产品,Redmi Buds 4和Redmi Buds 4 Pro,此前我们在Redmi Note11T
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • Flowable工作流引擎的科普与实践

    一.引言当我们在日常工作和业务中需要进行各种审批流程时,可能会面临一系列技术和业务上的挑战。手动处理这些审批流程可能会导致开发成本的增加以及业务复杂度的上升。在这
  • JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 花7万退货退款无门:谁在纵容淘宝珠宝商家造假?

    来源:极点商业作者:杨铭在淘宝购买珠宝玉石后,因为保证金不够赔付,店铺关闭,退货退款难、维权无门的比比皆是。&ldquo;提供相关产品鉴定证书,支持全国复检,可以30天无理由退换货。&
  • AI芯片初创公司Tenstorrent获三星和现代1亿美元投资

    Tenstorrent是一家由芯片行业资深人士Jim Keller领导的加拿大初创公司,专注于开发人工智能芯片,该公司周三表示,已经从现代汽车集团和三星投资基金等
  • iQOO 11S或7月上市:搭载“鸡血版”骁龙8Gen2 史上最强5G Soc

    去年底,iQOO推出了“电竞旗舰”iQOO 11系列,作为一款性能强机,iQOO 11不仅全球首发2K 144Hz E6全感屏,搭载了第二代骁龙8平台及144Hz电竞屏,同时在快充
  • 世界人工智能大会国际日开幕式活动在世博展览馆开启

    30日上午,世界人工智能大会国际日开幕式活动在世博展览馆开启,聚集国际城市代表、重量级院士专家、国际创新企业代表,共同打造人工智能交流平台。上海市副市
Top