SpringBoot 单元测试——JUnit5

news2025/1/21 5:50:56

目录

1、JUnit5概述

1.1、JUnit5 构成

1.2、JUnit5 配置

1.2.1、导入 Junit5 开发场景

 1.2.2、Junit5 开发场景自动导入依赖项

2、JUnit5 使用

2.1、Jnuit5 测试代码开发

2.1.1、测试代码格式

2.1.2、测试样例 

2.2、JUnit5常用注解

 2.2.1、@Test :表示方法是测试方法。

 2.2.2、@DisplayName :为测试类或者测试方法设置展示名称

 2.2.3、@BeforeEach、@AfterEach、@BeforeAll、@AfterAll

 2.2.4、@Disabled :表示测试类或测试方法不执行

 2.2.5、@Timeout :表示测试方法运行如果超过了指定时间将会返回错误

 2.2.6、@RepeatedTest :表示方法可重复执行

 2.2.7、其他注解

2.3、Jnuit5 断言(assertions)

 2.3.1、简单断言

 2.3.2、数组断言

 2.3.3、组合断言

 2.3.4、异常断言

 2.3.5、超时断言

 2.3.6、快速失败

2.4、前置条件

2.5、嵌套测试

2.6、参数化测试


1、JUnit5概述

1.1、JUnit5 构成

 JUnit5 由三个不同子项目的几个不同模块组成。

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

 1)JUnit Platform: 是在JVM上启动测试框架的基础,不仅支持Junit自制的测试引擎,其他测试引擎也都可以接入。

 2)JUnit Jupiter: 提供了JUnit5的新的编程模型,是JUnit5新特性的核心。内部包含了一个测试引擎,用于在Junit Platform上运行。

 3)JUnit Vintage: 由于JUint已经发展多年,为了照顾老的项目,其提供了兼容JUnit4.x,Junit3.x的测试引擎。

1.2、JUnit5 配置

1.2.1、导入 Junit5 开发场景

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

 1.2.2、Junit5 开发场景自动导入依赖项

 

2、JUnit5 使用

2.1、Jnuit5 测试代码开发

2.1.1、测试代码格式

 @SpringBootTest注解:添加在需要依赖springboot框架的测试类上,

                                        不然不能使用Springboot的相关开发功能

@Test注解:添加在测试方法上

@SpringBootTest
class Boot05WebAdminApplicationTests {

    @Test
    void contextLoads() {

    }
}

2.1.2、测试样例 

@Slf4j
@SpringBootTest
class SpringBootThymeleafApplicationTests {

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    DataSource dataSource;

    @Autowired
    UserMapper userMapper;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        Long along = jdbcTemplate.queryForObject("select count(*) from account", long.class);
        log.info("记录总数{}", along);
        log.info("数据源类型{}", dataSource.getClass());
    }

    @Test
    void testUserMapper() {
        User user = userMapper.selectById(1);
        log.info("用户信息{}", user);
    }

    @Test
    void testRedis() {
        ValueOperations<String, String> operations = redisTemplate.opsForValue();

        operations.set("hello", "world");

        String hello = operations.get("hello");
        System.out.println(hello);
    }
}

2.2、JUnit5常用注解

 2.2.1、@Test :表示方法是测试方法。

@SpringBootTest
class Boot05WebAdminApplicationTests {

    @Test
    void contextLoads() {

    }
}

 2.2.2、@DisplayName :为测试类或者测试方法设置展示名称

 测试代码:

@DisplayName("junit5功能测试")
public class Junit5Test {

    @DisplayName("测试displayname注解")
    @Test
    void testDisplayName() {
        System.out.println(1);
    }
}

 输出结果:

 2.2.3、@BeforeEach、@AfterEach、@BeforeAll、@AfterAll

 注解功能:

注解功能

@BeforeEach

表示在每个单元测试之前执行

@AfterEach

表示在每个单元测试之后执行

@BeforeAll

表示在所有单元测试之前执行

@AfterAll

表示在所有单元测试之后执行

 测试代码: 

@SpringBootTest
@DisplayName("junit5功能测试")
public class Junit5Test {

    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 测试前置条件
     */
    @DisplayName("测试前置条件")
    @Test
    void testAssumptions() {
        Assumptions.assumeTrue(false, "结果不足true");
        System.out.println("11111");
    }

    @DisplayName("测试displayname注解")
    @Test
    void testDisplayName() {
        System.out.println(1);
    }

    @Disabled
    @DisplayName("测试2")
    @Test
    void test2() {
        System.out.println(2);
        System.out.println(jdbcTemplate.getClass());
    }

    @BeforeEach
    void testBeforeEach() {
        System.out.println("测试就要开始。。。");
    }

    @AfterEach
    void testAfterEach() {
        System.out.println("测试就要结束。。。");
    }

    @BeforeAll
    static void testBeforeAll() {
        System.out.println("所有测试就要开始。。。");
    }

    @AfterAll
    static void testAfterAll() {
        System.out.println("所有测试已经结束。。。");
    }
}

 输出结果: 

 2.2.4、@Disabled :表示测试类或测试方法不执行

 测试代码:

    @Disabled
    @DisplayName("测试2")
    @Test
    void test2() {
        System.out.println(2);
        System.out.println(jdbcTemplate.getClass());
    }

 2.2.5、@Timeout :表示测试方法运行如果超过了指定时间将会返回错误

 测试代码:设置执行时间为500ms,超时报错

    @Test
    @Timeout(value = 500, unit = TimeUnit.MILLISECONDS)
    void testTimeOut() throws InterruptedException {
        Thread.sleep(520);
    }

 返回结果:

 2.2.6、@RepeatedTest :表示方法可重复执行

 测试代码:

    @RepeatedTest(5)    //重复测试5次
    @DisplayName("测试3")
    @Test
    void test3() {
        System.out.println(3);
        System.out.println(jdbcTemplate.getClass());
    }

 执行结果:

 

 2.2.7、其他注解

 @ParameterizedTest :表示方法是参数化测试

 @Tag :表示单元测试类别

 @ExtendWith :为测试类或测试方法提供扩展类引用

2.3、Jnuit5 断言(assertions)

  • 检查业务逻辑返回的数据是否合理。
  • 所有的测试运行结束以后,会有一个详细的测试报告;

 2.3.1、简单断言

 1)简单断言功能:

方法

说明

assertEquals

判断两个对象或两个原始类型是否相等

assertNotEquals

判断两个对象或两个原始类型是否不相等

assertSame

判断两个对象引用是否指向同一个对象

assertNotSame

判断两个对象引用是否指向不同的对象

assertTrue

判断给定的布尔值是否为 true

assertFalse

判断给定的布尔值是否为 false

assertNull

判断给定的对象引用是否为 null

assertNotNull

判断给定的对象引用是否不为 null

 2)测试代码:

@SpringBootTest
@DisplayName("junit5功能测试")
public class Junit5Test {
    @DisplayName("测试简单断言")
    @Test
    void testSimpleAssertions() {
        int call = call(1,2);
        assertEquals(2, call, "业务逻辑计算失败");

        Object obj1 = new Object();
        Object obj2 = new Object();
        assertSame(obj1, obj2, "两个对象不一样");
    }

    int call (int x, int y) {
        return x + y;
    }
    }
}

 3)测试结果:

 2.3.2、数组断言

 通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等

 测试代码:

@Test
@DisplayName("array assertion")
public void array() {
 assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}

 2.3.3、组合断言

  • assertAll 方法接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言

    • 可以通过 lambda 表达式很容易的提供这些断言

    • 前边断言失败,后续代码不会执行 

    • 组合断言,当组合中的所有断言都通过才是true,否则是false

 测试代码:

@Test
@DisplayName("assert all")
public void all() {
 assertAll("Math",
    () -> assertEquals(2, 1 + 1),
    () -> assertTrue(1 > 0)
 );
}

 2.3.4、异常断言

 JUnit5提供了Assertions.assertThrows() ,配合函数式编程就可以进行使用。

    @Test
    @DisplayName("异常断言")
    public void exceptionTest() {
        ArithmeticException exception = Assertions.assertThrows(
                //扔出断言异常
                ArithmeticException.class, () -> System.out.println(1 % 0));

    }

 2.3.5、超时断言

 Junit5提供了Assertions.assertTimeout() 为测试方法设置了超时时间

@Test
@DisplayName("超时测试")
public void timeoutTest() {
    //如果测试方法时间超过1s将会异常
    Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500));
}

 2.3.6、快速失败

  • 当满足某一条件,需要退出测试程序时,可以使用快速失败方法
  • 当调用快速失败方法时,程序会退出,同时输出失败提示
@Test
@DisplayName("fail")
public void shouldFail() {
 fail("This should fail");
}

2.4、前置条件

  • JUnit 5 中的前置条件(assumptions【假设】)类似于断言,
  • 不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止
  • 前置条件可以看成是测试方法执行的前提,当该前提不满足时,就没有继续执行的必要。

 测试代码:

@SpringBootTest
@DisplayName("junit5功能测试")
public class Junit5Test {

    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 测试前置条件
     */
    @DisplayName("测试前置条件")
    @Test
    void testAssumptions() {
        Assumptions.assumeTrue(false, "结果不足true");
        System.out.println("11111");
    }
}

返回结果:

        1.当不满足前置条件时,后续输出代码未执行

        2.当不满足前置条件时,程序未报错退出,而是终止执行

2.5、嵌套测试

  • JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试
  • 将相关的测试方法组织在一起。
  • 在内部类中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的层次没有限制。

 注意:

 1.外层测试方法的执行,不会驱动内层方法:

    当内层方法中有 before 或 after 等注解时,调用外层测试方法,并不会驱动其提前或最后执行

 2.内层方法的执行,可以驱动外层方法:

    当外层方法定义了某一数据结果时,内层测试方法可以直接调用该结构

 测试代码:

@DisplayName("嵌套测试")
public class TestingAstackDemo {

    Stack<Object> stack;

    @ParameterizedTest
    @DisplayName("参数化测试")
    @ValueSource(ints = {1, 2, 3, 4, 5})
    void testParamterized(int i) {
        System.out.println(i);
    }

    @ParameterizedTest
    @DisplayName("参数化方法测试")
    @MethodSource("stringProvider")
    void testParamterized2(String s) {
        System.out.println(s);
    }

    static Stream<String> stringProvider() {
        return Stream.of("apple", "banana");
    }

    @Test
    @DisplayName("is instantiated with new Stack()")
    void isInstantiatedWithNew() {
        new Stack<>();
        //在嵌套测试情况下,外层的test不能驱动内层
        //的beforeall等方法,在提前/之后运行
        //内层的test可以驱动外层
//        assertNotNull(stack);
    }

    @Nested
    @DisplayName("when new")
    class WhenNew {

        @BeforeEach
        void createNewStack() {
            stack = new Stack<>();
        }

        @Test
        @DisplayName("is empty")
        void isEmpty() {
            assertTrue(stack.isEmpty());
        }

        @Test
        @DisplayName("throws EmptyStackException when popped")
        void throwsExceptionWhenPopped() {
            assertThrows(EmptyStackException.class, stack::pop);
        }

        @Test
        @DisplayName("throws EmptyStackException when peeked")
        void throwsExceptionWhenPeeked() {
            assertThrows(EmptyStackException.class, stack::peek);
        }

        @Nested
        @DisplayName("after pushing an element")
        class AfterPushing {

            String anElement = "an element";

            @BeforeEach
            void pushAnElement() {
                stack.push(anElement);
            }

            @Test
            @DisplayName("it is no longer empty")
            void isNotEmpty() {
                assertFalse(stack.isEmpty());
            }

            @Test
            @DisplayName("returns the element when popped and is empty")
            void returnElementWhenPopped() {
                assertEquals(anElement, stack.pop());
                assertTrue(stack.isEmpty());
            }

            @Test
            @DisplayName("returns the element when peeked but remains not empty")
            void returnElementWhenPeeked() {
                assertEquals(anElement, stack.peek());
                assertFalse(stack.isEmpty());
            }
        }
    }
}

2.6、参数化测试

 1)参数化测试,可以指定测试方法的输入参数

 2)参数化测试的注解类型:

注解

功能

@ValueSource

为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型

@NullSource

表示为参数化测试提供一个null的入参

@EnumSource

表示为参数化测试提供一个枚举入参

@CsvFileSource

表示读取指定CSV文件内容作为参数化测试入参

@MethodSource

表示读取指定方法的返回值作为参数化测试入参(方法的返回值为流)

 测试代码:

        1)入参为基础类型

    @ParameterizedTest
    @DisplayName("参数化测试")
    @ValueSource(ints = {1, 2, 3, 4, 5})
    void testParamterized(int i) {
        System.out.println(i);
    }

         2)入参为方法返回值类型

    @ParameterizedTest
    @DisplayName("参数化方法测试")
    @MethodSource("stringProvider")
    void testParamterized2(String s) {
        System.out.println(s);
    }

    static Stream<String> stringProvider() {
        return Stream.of("apple", "banana");
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/408604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生 | 23】Docker运行Web服务实战之Tomcat

作者简介&#xff1a;&#x1f3c5;云计算领域优质创作者&#x1f3c5;新星计划第三季python赛道第一名&#x1f3c5; 阿里云ACE认证高级工程师&#x1f3c5; ✒️个人主页&#xff1a;小鹏linux &#x1f48a;个人社区&#xff1a;小鹏linux&#xff08;个人社区&#xff09;欢…

利用vue+高德地图API 实现用户的运动轨迹

利用vue高德地图API 实现用户的运动轨迹 高德地图网址&#xff1a;https://lbs.amap.com/api/jsapi-v2/guide/abc/prepare 任务一&#xff1a;实现地图显示 先完成准备工作&#xff0c;这一步是后面工作的基础。准备工作部分参考了&#xff1a; https://blog.csdn.net/qq_5…

vue3中vite的@路径别名与path中的resolve

使用路径引用 在vue3中&#xff0c;想用符号代替./…/这种相对路径引用使用&#xff0c; 前者相当于从根目录往后找&#xff0c;后者相当于从后往前找。 具体方法就是在vite.config.js中 import { resolve } from "path"export default defineConfig({plugins: [v…

Vue动态组件

等疫情结束了&#xff0c;要开始爬爬山、看看海&#xff0c;做些不会后悔的事情 一、概念 1. 示例 组件是可复用的 Vue 实例&#xff0c;且带有一个名字&#xff0c;这里实现一个最简单的组件&#xff1a; 父组件&#xff1a; <template><div><h1>Father…

【让CSDN的浪漫弥漫女神节】_Unity基础不动山不摇_回顾篇

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

promise 以及经典面试题

1.Promise 它是一个ES6提出一个新语法&#xff0c;用来优化异步代码的写法。promise&#xff1a;承诺 ● 生活中&#xff0c;它是用来表述 对将来要发生的事情的肯定。 例如 &#xff1a; 高中生说&#xff0c;老师&#xff0c;我会考上一所好大学的&#xff1b;销售员说&…

刷题日常计~JS④

作者 : SYFStrive 博客首页 : 点击跳转HomePage &#x1f4dc;&#xff1a; 初编程JavaScript之每天10&#x1f5e1;5题 &#x1f449; 从质变到量变&#x1f4aa; &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区…

Ajax 前后端数据交互

ajax 数据交互 今天又是奋斗的一天&#xff0c;行吧&#xff0c;来学习ajax ajax 数据交互什么是ajax&#xff1f;ajax的优势ajax的使用创建一个ajax对象配置这个对象发送请求接受返回过来的数据ajax状态码readystatechangeresponseTextajax请求方式封装一个属于自己的ajax什么…

2022年最新最详细在IDEA中配置Tomcat(含有详细图解过程)、建立使用IEDA建立一个Web项目的案例

1、首先已经成功安装过tomcat 如果没有成功安装&#xff0c;参考这篇tomcat安装教程(安装成功可忽略)&#xff1a;https://blog.csdn.net/weixin_43304253/article/details/117001797 2、在IDEA中配置tomcat的详细步骤 2.1、run ->Edit Confifurations 2.2 、点击加号 2.…

微信小程序自定义导航栏,实现不同用户角色登陆后显示不同的tabbar(避坑版)

在我们开发小程序的过程中&#xff0c;会遇到权限登录问题&#xff0c;不同的角色登录后显示的底部导航栏tabbar是不一样的。网上看到了很多的博客&#xff0c;多多少少会有些坑&#xff0c;会遇到问题。今天这篇博客就可以一次性解决。 了解概念 自定义tabbar 使用方法 app…

React修改Antd组件样式的方法

1.修改默认组件样式和写自己组件样式的区别 当我们写自己的样式时&#xff0c;在组件页面中定义class名称&#xff0c;再在less文件中对这个class定义样式。 //index.js import React,{useState} from react; import styles from ./index.less;const Index (props) >{ret…

36.一文讲透JavaScript日期对象Date,时间戳、1970、date方法、date计算

文章目录JavaScript日期和时间处理方法Date对象的创建new Date()new Date(milliseconds)1970年之前的时间&#xff1f;new Date(date_str)new Date(year, month, date, hours, minutes, sec, ms)Date对象的方法获取日期内容设置日期内容日期的自动校准日期转为数字、日期差值Da…

Node.js安装及环境配置之Windows篇

Node.js安装及环境配置之Windows篇Node.js安装及环境配置之Windows篇一、安装环境二、安装node.js步骤三、前期准备四、开始安装五、环境配置Node.js安装及环境配置之Windows篇 一、安装环境 1、本机系统&#xff1a;Windows 10&#xff08;64位&#xff09; 2、Node.js&…

纯js判断文件流格式类型:pdf,doc,docx,xls,xlsx,ppt,pptx一次搞定!

目录使用js判断文件类型的场景方法特点输入输出方法步骤1. 查看每种格式文件的16进制码&#xff0c;提取不同文件类型的“特征数”。2. 先判断大类型&#xff0c;在具体大类下判断小类型项目地址&#xff1a;纯前端基于react实现的多类型文件预览&#xff1a;通过arraybuffer判…

uniapp全局组件全局使用(不在每个页面template使用,仅支持H5),函数式调用全局组件方法

最简单的使用&#xff0c;在 main.js 编写如下代码&#xff0c;即可将 xxx 组件在每个页面显示 // main.js// 引入组件 import xxx from "/components/xxx.vue";// 将该组件挂载在document.body下 document.body.appendChild(new xxx().$mount().$el); 函数式调用全…

JS高级知识总结

文章目录1. this指向问题2. 对象进阶2.1 对象的定义和使用2.2 对象访问器2.2.1 Getter2.2.2 Setter2.3 对象构造器2.4 对象原型2.4.1 prototype属性2.4.2 \_\_proto\_\_ 属性2.4.3 constructor属性2.4.4 原型链2.5 Object对象2.5.1 管理对象2.5.2 保护对象3. 函数进阶3.1 函数的…

.Net Core中间件

目录 一、什么是中间件 二、中间件的用途 三、中间件的三个概念 四、自定义中间件 五、ASP.NET Core附带中间件组件 六、中间件和过滤器的区别 一、什么是中间件 在浏览网站或者使用手机App加载内容的时候&#xff0c;浏览器或者手机App其实在向Web服务器发送HTTP请求。服…

NodeJS安装(npm包管理器)

1、nodejs下载 windows下的NodeJS安装是比较方便的&#xff0c; 只需要登陆官网&#xff08;Node.js&#xff09;&#xff0c;直接点击64-bit下载安装 2、安装过程基本直接“NEXT”&#xff0c;NodeJS已经集成了npm&#xff0c;所以npm也一并安装好了 3、在cmd窗口输入node -…

React-DevTools开发者工具安装

React开发者工具最简单的安装方式自然是科学上网&#xff0c;通过Google Chrome浏览器访问应用商店安装了。以下介绍另一种安装方式&#xff1a;基于 react-devtools的GitHub项目源码编译进行插件安装。 目录 React-DevTools&#xff1a;GitHub项目地址 React-DevTools&#x…

修改elementUI中el-date-picker内置样式

一.编写背景 今天正在日常的需求编写和bug调试中&#xff0c;产品提出了这样一个需求。为了满足用户在新增数据时的便捷准确&#xff0c;时间选择格式为“年月日时”&#xff0c;即用户不需要选择分合秒&#xff0c;换句话说就是下图中红色框的两项不需要。 二.问题分析。 当时…