Spring Boot 集成 JUnit5,更优雅单元测试!

简介: JUnit4被广泛使用,但是许多场景下使用起来语法较为繁琐,JUnit5中支持lambda表达式,语法简单且代码不冗余。

为什么使用JUnit5

  • JUnit4被广泛使用,但是许多场景下使用起来语法较为繁琐,JUnit5中支持lambda表达式,语法简单且代码不冗余。
  • JUnit5易扩展,包容性强,可以接入其他的测试引擎。
  • 功能更强大提供了新的断言机制、参数化测试、重复性测试等新功能。
  • ps:开发人员为什么还要测试,单测写这么规范有必要吗?其实单测是开发人员必备技能,只不过很多开发人员开发任务太重导致调试完就不管了,没有系统化得单元测试,单元测试在系统重构时能发挥巨大的作用,可以在重构后快速测试新的接口是否与重构前有出入。

简介

image.png

如图,JUnit5结构如下:

  • JUnit Platform :这是Junit提供的平台功能模块,通过它,其它的测试引擎都可以接入Junit实现接口和执行。
  • JUnit JUpiter :这是JUnit5的核心,是一个基于JUnit Platform的引擎实现,它包含许多丰富的新特性来使得自动化测试更加方便和强大。
  • JUnit Vintage :这个模块是兼容JUnit3、JUnit4版本的测试引擎,使得旧版本的自动化测试也可以在JUnit5下正常运行。

依赖引入

我们以SpringBoot2.3.1为例,引入如下依赖,防止使用旧的junit4相关接口我们将其依赖排除。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

常用注解

  • @BeforeEach:在每个单元测试方法执行前都执行一遍
  • @BeforeAll:在每个单元测试方法执行前执行一遍(只执行一次)
  • @DisplayName("商品入库测试"):用于指定单元测试的名称
  • @Disabled:当前单元测试置为无效,即单元测试时跳过该测试
  • @RepeatedTest(n):重复性测试,即执行n次
  • @ParameterizedTest:参数化测试,
  • @ValueSource(ints = {1, 2, 3}):参数化测试提供数据

断言

JUnit Jupiter提供了强大的断言方法用以验证结果,在使用时需要借助java8的新特性lambda表达式,均是来自org.junit.jupiter.api.Assertions包的static方法。

assertTrue`与`assertFalse`用来判断条件是否为`true`或`false
Copy    @Test
    @DisplayName("测试断言equals")
    void testEquals() {
        assertTrue(3 < 4);
    }
assertNull`与`assertNotNull`用来判断条件是否为·`null
    @Test
    @DisplayName("测试断言NotNull")
    void testNotNull() {
        assertNotNull(new Object());
    }

assertThrows用来判断执行抛出的异常是否符合预期,并可以使用异常类型接收返回值进行其他操作

@Test
    @DisplayName("测试断言抛异常")
    void testThrows() {
        ArithmeticException arithExcep = assertThrows(ArithmeticException.class, () -> {
            int m = 5/0;
        });
        assertEquals("/ by zero", arithExcep.getMessage());
    }

assertTimeout用来判断执行过程是否超时

@Test
    @DisplayName("测试断言超时")
    void testTimeOut() {
        String actualResult = assertTimeout(ofSeconds(2), () -> {
            Thread.sleep(1000);
            return "a result";
        });
        System.out.println(actualResult);
    }

assertAll是组合断言,当它内部所有断言正确执行完才算通过

@Test
    @DisplayName("测试组合断言")
    void testAll() {
        assertAll("测试item商品下单",
                () -> {
                    //模拟用户余额扣减
                    assertTrue(1 < 2, "余额不足");
                },
                () -> {
                    //模拟item数据库扣减库存
                    assertTrue(3 < 4);
                },
                () -> {
                    //模拟交易流水落库
                    assertNotNull(new Object());
                }
        );
    }

重复性测试

在许多场景中我们需要对同一个接口方法进行重复测试,例如对幂等性接口的测试。

JUnit Jupiter通过使用@RepeatedTest(n)指定需要重复的次数

@RepeatedTest(3)
    @DisplayName("重复测试")
    void repeatedTest() {
        System.out.println("调用");
    }

image.gif

参数化测试

参数化测试可以按照多个参数分别运行多次单元测试这里有点类似于重复性测试,只不过每次运行传入的参数不用。需要使用到@ParameterizedTest,同时也需要@ValueSource提供一组数据,它支持八种基本类型以及String和自定义对象类型,使用极其方便。

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
@DisplayName("参数化测试")
    void paramTest(int a) {
            assertTrue(a > 0 && a < 4);
        }

内嵌测试

JUnit5提供了嵌套单元测试的功能,可以更好展示测试类之间的业务逻辑关系,我们通常是一个业务对应一个测试类,有业务关系的类其实可以写在一起。这样有利于进行测试。而且内联的写法可以大大减少不必要的类,精简项目,防止类爆炸等一系列问题。

@SpringBootTest
@AutoConfigureMockMvc
@DisplayName("Junit5单元测试")
public class MockTest {
    //....
    @Nested
    @DisplayName("内嵌订单测试")
    class OrderTestClas {
        @Test
        @DisplayName("取消订单")
        void cancelOrder() {
            int status = -1;
            System.out.println("取消订单成功,订单状态为:"+status);
        }
    }
}

相关文章
|
7月前
|
存储 人工智能 测试技术
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
141428 29
小鱼深度评测 | 通义灵码2.0,不仅可跨语言编码,自动生成单元测试,更炸裂的是集成DeepSeek模型且免费使用,太炸裂了。
|
10月前
|
敏捷开发 测试技术 持续交付
探索软件测试中的自动化与持续集成
在快速迭代的软件开发环境中,自动化测试和持续集成(CI)已成为确保产品质量和加速交付的关键策略。本文将深入探讨自动化测试的基本原理、实施步骤以及它如何与持续集成流程相结合,以提高软件开发的效率和可靠性。我们将通过实际案例分析,展示自动化测试和CI的最佳实践,以及它们如何帮助企业实现更快的市场响应时间和更高的客户满意度。
135 16
|
10月前
|
jenkins 测试技术 持续交付
软件测试中的自动化与持续集成:提升效率与质量的关键
在快节奏的软件开发环境中,自动化测试和持续集成已经成为不可或缺的部分。本文将探讨自动化测试和持续集成的重要性,以及它们如何协同工作以提高软件开发的效率和质量。通过分析自动化测试的策略、工具选择以及持续集成的实践,我们将揭示这些技术如何帮助开发团队快速响应变化,减少错误,并加速产品上市时间。
|
10月前
|
机器学习/深度学习 人工智能 jenkins
软件测试中的自动化与持续集成实践
在快速迭代的软件开发过程中,自动化测试和持续集成(CI)是确保代码质量和加速产品上市的关键。本文探讨了自动化测试的重要性、常见的自动化测试工具以及如何将自动化测试整合到持续集成流程中,以提高软件测试的效率和可靠性。通过案例分析,展示了自动化测试和持续集成在实际项目中的应用效果,并提供了实施建议。
|
10月前
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
7月前
|
人工智能 IDE 测试技术
用户说 | 通义灵码2.0,跨语言编码+自动生成单元测试+集成DeepSeek模型且免费使用
通义灵码, 作为国内首个 AI 程序员,从最开始的内测到公测,再到通义灵码正式发布第一时间使用,再到后来使用企业定制版的通义灵码,再再再到现在通义灵码2.0,我可以说“用着”通义灵码成长的为数不多的程序员之一了吧。咱闲言少叙,直奔主题!今天,我会聊一聊通义灵码的新功能和通义灵码2.0与1.0的体验感。
|
9月前
|
jenkins 测试技术 持续交付
软件测试中的自动化与持续集成
在现代软件开发过程中,自动化测试和持续集成已成为不可或缺的组成部分。本文将深入探讨自动化测试和持续集成的重要性、优势以及如何有效实施它们以提升软件质量和开发效率。通过具体案例分析,我们将展示这些技术如何在实际项目中发挥作用,并讨论其面临的挑战及应对策略。
228 60
|
7月前
|
人工智能 IDE 测试技术
用户说 | 通义灵码2.0,跨语言编码+自动生成单元测试+集成DeepSeek模型且免费使用
用户说 | 通义灵码2.0,跨语言编码+自动生成单元测试+集成DeepSeek模型且免费使用
|
9月前
|
机器学习/深度学习 人工智能 jenkins
探索软件测试中的自动化与持续集成
【10月更文挑战第21天】 在软件开发的生命周期中,软件测试扮演着至关重要的角色。随着技术的进步和开发模式的转变,自动化测试和持续集成已经成为提高软件质量和效率的关键手段。本文将深入探讨自动化测试和持续集成的概念、实施策略以及它们如何相互配合以优化软件开发流程。我们将通过分析实际案例,展示这些技术如何在实际项目中发挥作用,以及面临的挑战和解决方案。此外,文章还将讨论未来趋势,包括人工智能在测试领域的应用前景。
227 17
|
10月前
|
Devops 测试技术 持续交付
软件测试中的自动化与持续集成:最佳实践与挑战
在快速迭代的软件开发周期中,自动化测试和持续集成(CI)已成为提高软件质量和加速产品上市的关键策略。本文探讨了自动化测试和CI的实施如何帮助开发团队提前发现缺陷、缩短反馈循环,并确保代码质量。我们将深入分析自动化测试的策略选择、工具应用以及面临的挑战,同时提供一些克服这些挑战的最佳实践。
305 27