九、Junit5的使用

九、Junit5的使用

1、Junit5概述
  • Junit5与之前发布Junit框架有很大的不同,由3个不同的子项目的模块组成
    • Junit5 = Junit Platform + Junit Jupiter + Junit Vintage
  • Junit Platform :Junit Platform 是在JVM上启动测试框架的基础,不仅仅支持Junit自制的测试引擎,其他测试引擎也可以接入
  • Junit Jupiter :Junit Jupiter提供了Junit5的新的编程模型,是Junit5新特性的核心,内部包含了一个测试引擎,用于在Junit Platform上运行
  • Junit Vintage :由于Junit发展多年,为了照顾老的项目,Junit Vintage提供了兼容Junit4和Junit3的测试引擎
  • 更多细节以及使用参见Junit5官网 :JUnit 5
2、SpringBoot对Junit5的支持
  • SpringBoot 2.4及其以上版本移除了默认对Vintage的依赖,如果需要兼容Junit4需要自行引入(不能使用Junit4的测试功能)

    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.hamcrest</groupId>
                <artifactId>hamcrest-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
  • 给出一个SpringBoot测试类的例子

    import org.junit.jupiter.api.Test;// 这里是jupiter包下的,junit4是在org.junit包下
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest //使用该注解后,可以使用自动注入(@Autowried)等功能
    class DataMainApplicationTests {
    
        @Test//junit5的测试注解,并不是Junit4里面的@Test注解了
        void contextLoads() {
    
        }
    }
    
  • 使用Junit5测试框架的前提肯定是要导入junit启动器啦

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
3、Junit5中的常用注解
注解描述
@Test表示方法是测试方法,与Junit4不同,功能单一不能声明任何属性,由Jupiter提供额外测试
@ParameterizedTest表示方法是参数化测试
@RepeatedTest表示方法可以重复执行,参数指定重复执行次数
@DisplayName为测试类或者测试方法设置展示名称
@Beforeach表示在每个单元测试之前执行
@AfterEach表示在每个单元测试之后执行
@BeforeAll表示在所有单元测试之前执行
@AfterAll表示在所有单元测试之后执行
@Tag表示单元测试类别
@Disabled表示测试类或测试方法不执行
@Timeout表示测试方法运行如果超过了指定时间将会返回错误
@ExtendWith为测试类或测试方法提供扩展类引用
4、Junit5中的断言(assertions)
  • 断言(assertions)是测试方法中的核心部分,用来对测试需要满足的条件进行验证。这些断言方法都是 org.junit.jupiter.api.Assertions 类的静态方法,对于断言:检查业务逻辑返回的数据是否合理,所有的测试运行结束以后,会有一个详细的测试报告

  • 简单断言:用来对单个值进行简单的验证

    方法描述
    asserEquals判断两个对象或两个原始类型是否相等
    assertNotEquals判断两个对象或两个原始类型是否不相等
    assertSame判断两个独享引用是否指向同一个对象
    assertNotSame判断连个对象引用是否指向不同的对象
    aeertTrue判断给定的布尔值是否为true
    assertFalse判断给定的布尔值是否为false
    assertNull判断给定的对象引用是否为null
    assertNotNull判断给定的对象引用是否不为null
    • 例子:asserEquals

      @Test
      public void test1(){
          //参数一:期望的值 参数二:实际执行的值 参数三:不同的构造器,可以设置提示信息
          assertEquals(1,3,"预期和实际执行后的对象或基本数据类型是不相等");
      	// 注意:若含有多个断言方法,中间有任何断言方法报出提示信息,后面的断言将不再执行
      }
      
  • 数组断言(assertArrayEquals)

    @Test
    @DisplayName("array assertion")
    public void array() {
        //通过assertArrayEquals() 方法来判断两个对象或原始类型的数组是否相等
     	assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
    }
    
  • 组合断言(assertAll)

    @Test
    public void test2(){
        // assertAll() 方法接收多个org.junit.jupiter.api.Executable函数式接口的实例
        //作为要验证的断言,可以通过lambda表达式很容易就提供这些断言
       	assertAll(
             "组合断言",
             () -> assertEquals(2,1 + 1),//使用lambda表达式
             () -> assertNotEquals(2,1 + 1)
       );
    }
    
  • 异常断言(assertThrows)

    @Test
    @DisplayName("异常测试")
    public void exceptionTest() {
        //Junit5提供了一种全新的断言方式Assertions.assertThrows(),配合函数式编程就可以使用
        ArithmeticException exception = Assertions.assertThrows(
               //扔出断言异常
                ArithmeticException.class, () -> System.out.println(1 % 0));
    }
    
  • 超时断言(assertTimeout)

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

    @Test
    @DisplayName("fail")
    public void shouldFail() {
    	fail("This should fail");
    }
    
5、前置条件
  • Junit5中的前置条件(assumptions[假设])类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。前置条件可以看成是测试号方法执行的前提,当该前提不满足时,就没有继续执行的必要了

    @Test
    @DisplayName("前置条件")
    public void test3(){
        Assumptions.assumeTrue(true,"断言信息");//assumeTrue : 期望值true
        Assumptions.assumeFalse(false,"前置条件为false");//assumeFalse : 期望值为false
        System.out.println("若前置条件失败,我不会输出");
    }
    
6、嵌套测试
  • Junit5可以通过java的内部类和@Nested注解实现嵌套测试,从而可以更好的把线管的测试方法组织在一起,在内部类中可以使用@BeforeEach和@AfterEach注解,而且嵌套的层次没有限制

  • 外层的@Test不能驱动内层的@Test 内层的可以驱动外层的@Test

    @DisplayName("A stack")
    class TestingAStackDemo {
    
        Stack<Object> stack;
    
        @Test
        @DisplayName("is instantiated with new Stack()")
        void isInstantiatedWithNew() {
            new 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());
                }
            }
        }
    }
    
7、参数化测试
  • 参数化测试时Junit5很重要的一个新特性,它使得用不同的参数多次运行测试成为可能,利用参数化测试注解,省去了很多冗余的代码

    参数化测试注解描述
    @ValueSource为参数化测试指定入参来源,支持八大基础类以及Stirng类型,Class类型
    @NullSource为参数化测试提供一个null的入参
    @EnumSource为参数化测试提供一个枚举入参
    @CsvFileSource读取指定CSV文件内容作为参数化测试入参
    @MethodSource表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)
  • 下面一个例子

        @ParameterizedTest//注意,参数化测试不在使用@Test注解,而是@ParameterizedTest注解
        @DisplayName("参数化测试")
        @ValueSource(ints = {1,2,3,4,5})
        public void test4(int i){
            System.out.println(i);
        }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值