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

这篇具有很好参考价值的文章主要介绍了深度揭秘JUnit5与Mockito的单元测试神秘面纱。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

  提示: 今天的代码是在第九天代码的基础上进行开发,我们将为UserController中添加更多的单元测试方法,以展示JUnit和Mockito的强大功能。

  核心知识介绍:

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

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

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

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

  以下是一些常用的 MethodOrderer 实现:

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

  代码示例:

  在今天的代码示例中,我们将在昨天的基础上进一步完善UserController的单元测试,使用JUnit和Mockito来验证控制器层的方法是否按照预期执行。

  在 pom.xml 文件增加增加测试依赖

<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.java

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模拟依赖,我们揭开了单元测试的神秘面纱,为更健壮的代码打下了坚实的基础。

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

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

  总体而言,通过今天的学习,我们不仅深入了解了单元测试的基本原理,还学会了如何在Spring Boot项目中使用JUnit5和Mockito框架进行测试,为后续更复杂的业务逻辑和代码改动提供了可靠的测试基础。

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

 深度揭秘JUnit5与Mockito的单元测试神秘面纱,单元测试,功能测试,测试工具,安全性测试,测试用例,postman,selenium

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取 

深度揭秘JUnit5与Mockito的单元测试神秘面纱,单元测试,功能测试,测试工具,安全性测试,测试用例,postman,selenium文章来源地址https://www.toymoban.com/news/detail-786362.html

到了这里,关于深度揭秘JUnit5与Mockito的单元测试神秘面纱的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot项目使用Junit5 + mockito + jacoco 实现单元测试以及代码覆盖率检查

    在创建springboot项目时会默认添加spring-boot-starter-test依赖,其中已经包含了junit、mockito依赖,根据springboot版本的不同junit和mockito的版本也会有所不同 先说一下各自功能: junit只说一点,junt4和junit5的注解不同,使用方式略有差异,其他不赘述了,基本用法都懂。 mockito是mock的

    2023年04月23日
    浏览(41)
  • 单元测试框架——Junit5

    Junit是一个开源的用于Java语言的单元测试框架,也是Java方向使用最广泛的单元测试框架。 在pom.xml中引入Junit5相关依赖 @Test :表示一个方法/用例 BeforeEach :表示被注解的方法在其它所有方法执行前都要执行一遍,也就是说其它方法有3个它就要执行3遍 @BeforeAll :表示被注解的

    2024年02月11日
    浏览(35)
  • Junit5单元测试框架详解

    前面我们学习了Selenium自动化测试框架,但是有的时候测试用例会很多,我们需要一个工具来管理这些测试用例,而Junit就是一个很好的管理工具,简单点来说,Junit就是一个针对Java的单元测试框架; 目录 一. 关于Junit5 二. Junit使用 2.1 添加Maven依赖 2.2 注解 2.3 断言 2.4 套件

    2024年02月06日
    浏览(35)
  • JUnit5-单元测试操作详解

    JUnit 5是JUnit测试框架的下一个主要版本,用于编写和运行单元测试。 与以前版本的 JUnit 不同,JUnit 5 由来自三个不同子项目的多个不同模块组成。 JUnit 5 =  JUnit 平台 +  JUnit Jupiter  +  JUnit Vintage JUnit 平台 是在 JVM 上启动测试框架的基础。它还定义了 TestEngine 用于开发在平台

    2024年04月10日
    浏览(41)
  • 【单元测试】如何使用 JUnit5 框架?

      Junit5是一个用于在Java平台上进行单元测试的框架。JUnit 5 框架主要由三部分组成:JUnit Platform、JUnit Jupiter 和 JUnit Vintage。 JUnit Platform:定义了测试引擎的 API,是 JVM 上用于启动测试框架的基础服务,支持通过 IDE、构建工具、命令行等方式运行单元测试。 JUnit Jupiter:包含

    2024年04月10日
    浏览(36)
  • SpringBoot2---单元测试(Junit5)(1)

    org.junit.vintage junit-vintage-engine test org.hamcrest hamcrest-core org.springframework.boot spring-boot-starter-test test 现在版本: @SpringBootTest class Boot05WebAdminApplicationTests { @Test void contextLoads() { } } 以前: @SpringBootTest + @RunWith(SpringRunner.class) SpringBoot整合Junit以后。 编写测试方法:@Test标注(注意需要

    2024年04月29日
    浏览(33)
  • 13.Springboot整合junit5单元测试与生成单元测试覆盖率

    现在基本大公司都要求单元测试了,保证我们代码得质量,而我司更是要求覆盖率要达到60%以上,所以搞一下。 这里有两个方法: 1.使用maven自带得test,idea右侧maven模块执行项目下得test 2.使用cmd命令,在你的项目pom文件所在目录 ,打开cmd,执行如下: 结果如下:打开site文

    2024年02月16日
    浏览(27)
  • 静态方法 单元测试 springboot+mokito+junit5

    CodecUtils的方法是静态类,使用@InjectMocks不能有用,因为这个注解只能用于非静态的对象。 想要为静态方法写单元测试,可以使用Mockito.mockStatic(Class classToMock)方法,它可以返回一个MockedStatic对象,用于模拟静态方法的调用。 1.导入依赖 2.单元测试 可以参考如下地址,了解如何

    2024年04月25日
    浏览(35)
  • 【SpringBoot】mockito+junit 单元测试

    CommonServiceImpl 在方法 getSourceCodeMap() 调用了 ServiceA 的方法 list(QueryBO queryBo) 。 org.mockito.exceptions.base.MockitoException: No tests found in ClientSyncServiceImplTest Is the method annotated with @Test? Is the method public? 解决方案: Test引入 org.junit.Test 不要引入 org.junit.jupiter.api.Test 例如获取当前用户 moc

    2024年02月09日
    浏览(27)
  • 单元测试junit(原始版本、Spring Boot各版本、junit5)使用介绍

    🍓 简介:java系列技术分享(👉持续更新中…🔥) 🍓 初衷:一起学习、一起进步、坚持不懈 🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏 🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝 🍓 更多文章请点击 单元测试 junit各版本 使用介绍 官

    2023年04月16日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包