JUnit5 单元测试框架

Java生态中,Junit是使用最广泛的单元测试框架,JUnit能和Eclipse等主流集成开发环境整合,点击一个按钮即可运行测试,此外也能和Maven、Gradle等构建工具整合,在构建时运行单元测试并生成测试报告,功能非常强大。

JUnit4和JUnit5对比

在早些年间Junit4比较流行,但随着时间的推移目前JUnit5使用更为广泛,新版本SpringBoot的单元测试模块也是基于JUnit5,Junit4和JUnit5在使用上API稍有区别,JUnit5扩展了更多强大的功能,不过基本用法是一致的。

引入Maven依赖

使用JUnit5的基础功能需要2个模块,Junit Launcher定义了用于在开发平台上运行测试框架的API;Junit Jupiter定义了Junit注解和具体的TestEngine实现。

<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <version>1.9.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.0</version>
    <scope>test</scope>
</dependency>

JUnit Vintage主要用于兼容JUnit4或其它单元测试框架的历史遗留代码,如果不涉及可以不引入。

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.9.0</version>
    <scope>test</scope>
</dependency>

JUnit Jupiter Params是一个可选的扩展模块,能够实现参数化测试,我们可以用CSV等方式加载测试用例所需的数据,这里不展开介绍,具体可以参考文档。参数化测试因为包含测试用例读取的逻辑,因此相对更复杂一些,过度设计的测试驱动开发是条邪路,这里只建议在适合的场景使用合适的方案。

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.9.0</version>
    <scope>test</scope>
</dependency>

Eclipse中使用JUnit5

我们这里以Maven工程为例,在src/test/java文件夹下创建单元测试代码,建立的文件目录如下。

我们这里使用@Test注解标注单元测试方法。

package com.gacfox.demo;

import org.junit.jupiter.api.Test;

public class DemoTest {
    @Test
    public void testA() {
        System.out.println("Demo test");
    }
}

运行时,我们直接在单元测试方法上点击右键,并以JUnit Test方式运行;也可以直接在测试类上运行测试,此时会执行测试类中的所有单元测试方法。

运行完成后,相关的结果会显示在界面中。

如果由于某些原因运行失败,如图所示会显示相关信息。

JUnit5 API

下面我们介绍JUnit5中的API。

基本注解

我们先看最基本的几个注解:

  • @BeforeAll:在所有测试方法前运行,必须是静态方法
  • @AfterAll:在所有测试方法后运行,必须是静态方法
  • @BeforeEach:在测试类中每一个测试方法前运行
  • @AfterEach:在测试类中每一个测试方法后运行
  • @Test:标注为测试方法,可以在IDE或Maven等环境中触发单元测试执行
package com.gacfox.demo;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class DemoTest {
    @BeforeAll
    public static void testBeforeAll() {
        System.out.println("before all");
    }

    @AfterAll
    public static void testAfterAll() {
        System.out.println("after all");
    }

    @BeforeEach
    public void testBeforeEach() {
        System.out.println("before each");
    }

    @AfterEach
    public void testAfterEach() {
        System.out.println("after each");
    }

    @Test
    public void testA() {
        System.out.println("testA");
    }

    @Test
    public void testB() {
        System.out.println("testB");
    }
}

运行整个测试类的执行结果:

before all
before each
testA
after each
before each
testB
after each
after all

断言

JUnit5提供了一个新的Assertions断言类,其中包括了实现断言的静态方法,断言如果未实现,就会抛出运行时异常,抛出异常则意味着测试用例执行失败,测试未通过。

常用的断言包括:

  • assertEquals()assertNotEquals():根据对象equals()判断两个对象是否相等。
  • assertTrue()assertFalse():根据==运算符判断两个对象是否为同一个对象(基本类型为判断是否相等)。
  • assertNull()assertNotNull():判断参数对象是否为null

除此之外,JUnit还提供了很多实用的断言方法,这里就不全部列举了。使用断言的例子代码如下:

package com.gacfox.demo;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class DemoTest {

    @Test
    public void testA() {
        String a = new String("abc");
        String b = new String("abc");
        String c = null;
        Assertions.assertEquals(a, b);
        Assertions.assertFalse(a == b);
        Assertions.assertNull(c);
    }
}

上面测试用例可以运行通过。

重复测试

除了@Test注解,我们也可以使用@RepeatedTest标注测试方法入口,它支持一个int类型参数,能够实现多次重复执行一个测试方法。下面例子代码中,测试方法testA()会执行3次。

package com.gacfox.demo;

import org.junit.jupiter.api.RepeatedTest;

public class DemoTest {

    @RepeatedTest(3)
    public void testA() {
        System.out.println("重复测试");
    }
}

测试结果展示

@DisplayName可以用来标注单元测试类和方法的名字,支持JUnit5的IDE会以标注的名字显示测试结果。

package com.gacfox.demo;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

@DisplayName("我的第一个测试类")
public class DemoTest {

    @Test
    @DisplayName("我的第一个测试方法")
    public void testA() {
        System.out.println("testA");
    }
}

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap