Bootstrap

java系列2:java测试框架Junit5+Allure+Mockito

1. Junit5

1.1 框架

结构上变成了:JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

  • JUnit Platform: Junit Platform是在JVM上启动测试框架,可以接入各种引擎。
  • JUnit Jupiter: JUnit Jupiter提供了JUnit5的新的编程模型,是JUnit5新特性的核心。运行在上面的JUnit Platform中。
  • JUnit Vintage: 兼容JUnit4.x,Junit3.x测试引擎。
    web测试的话,可以用postman

下面是个简单的例子:

import org.junit.jupiter.api.Test; //注意这里使用的是jupiter的Test注解!!
public class TestDemo {
  @Test
  @DisplayName("第一次测试")
  public void firstTest() {
      System.out.println("hello world");
  }

1.2 注解

Junit5多了很多新的tag

@Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
@ParameterizedTest :表示方法是参数化测试,下方会有详细介绍
@RepeatedTest :表示方法可重复执行,下方会有详细介绍
@DisplayName :为测试类或者测试方法设置展示名称
@BeforeEach :表示在每个单元测试之前执行
@AfterEach :表示在每个单元测试之后执行
@BeforeAll :表示在所有单元测试之前执行
@AfterAll :表示在所有单元测试之后执行
@Tag :表示单元测试类别,类似于JUnit4中的@Categories
@Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
@Timeout :表示测试方法运行如果超过了指定时间将会返回错误
@ExtendWith :为测试类或测试方法提供扩展类引用

这里介绍一下tag。利用 Tag 标签,用户可以比较方便地根据标注来分类,并在执行时快速根据分类来针对性地运行测试。在 Junit5 中添加 Tag 是通过 @Tag 注解来实现的
Junit5 也支持直接读取自定义的注解,比如我们自定义一个注解 QiucaoTag,将 @Tag(“qiucao”) 和 @Test 注解聚合,来简化标注操作。

@QiucaoTag
void customTag(TestInfo info) {
    System.out.println(info.getTags());
}

自定义注解类如下:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("qiucao")
@Test
public @interface QiucaoTag {}

1.3 断言

除了传统的assertion外,JUnit5提供了一些新的断言方式。Assertions.assertThrows() ,配合函数式编程就可以进行使用。

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

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

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

1.4 参数化测试

@ValueSource:指定入参,支持八大基础类以及String类型,Class类型
@NullSource: 表示为参数化测试提供一个null的入参
@EnumSource: 表示为参数化测试提供一个枚举入参
下面是例子

@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("参数化测试1")
public void parameterizedTest1(String string) {
    System.out.println(string);
    Assertions.assertTrue(StringUtils.isNotBlank(string));
}

1.5 测试用例参数化

Junit5中支持给测试方法提供参数,提高了测试数据管理的便利性。内建的几种数据源

// ValueSource
@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
void testWithValueSource(int argument) {
   assertTrue(argument > 0 && argument < 4);
}
//EnumSource
@ParameterizedTest
@EnumSource(TimeUnit.class)
void testWithEnumSource(TimeUnit timeUnit) {
   assertNotNull(timeUnit);
}
//还可以提供数据的例外处理,正则匹配等
@ParameterizedTest
@EnumSource(value = TimeUnit.class, mode = EXCLUDE, names = { "DAYS", "HOURS" })
void testWithEnumSourceExclude(TimeUnit timeUnit) {
   assertFalse(EnumSet.of(TimeUnit.DAYS, TimeUnit.HOURS).contains(timeUnit));
   assertTrue(timeUnit.name().length() > 5);
}
//or
@ParameterizedTest
@EnumSource(value = TimeUnit.class, mode = MATCH_ALL, names = "^(M|N).+SECONDS$")
void testWithEnumSourceRegex(TimeUnit timeUnit) {
   String name = timeUnit.name();
   assertTrue(name.startsWith("M") || name.startsWith("N"));
   assertTrue(name.endsWith("SECONDS"));
}
//MethodSource
@ParameterizedTest
@MethodSource("stringProvider")
void testWithSimpleMethodSource(String argument) {
   assertNotNull(argument);
}
static Stream<String> stringProvider() {
   return Stream.of("foo", "bar");
}
//CsvSource
@ParameterizedTest
@CsvSource({ "foo, 1", "bar, 2", "'baz, qux', 3" })
void testWithCsvSource(String first, int second) {
     assertNotNull(first);
     assertNotEquals(0, second);
}
//CsvFileSource
@ParameterizedTest
@CsvFileSource(resources = "/two-column.csv", numLinesToSkip = 1)
void testWithCsvFileSource(String first, int second) {
     assertNotNull(first);
     assertNotEquals(0, second);
}

2. Allure

2.1 创建junit测试的方法

在要测试的类上按快捷键ctrl + shift + t,选择Create New Test,在出现的对话框的下面member内勾选要测试的方法,点击ok

或者点击菜单栏Navigate–>test,选择Create New Test,在出现的对话框的下面member内勾选要测试的方法,点击ok

2.2 Allure安装与配置。

详细安装步骤看这里
首先把junit配置好,去intelliJ idea->Preference->Plugins中,安装MavenTestSupportPlugin。然后选中要单元测试的项目,按command+shift+t生成test。注意junit5还要再安装两个库。

brew install allure #进行安装
allure --version # 查看版本号
#这个命令最常使用的,生成web报告。
allure serve [path of allure result] 
# 生成测试报告,可以携带一个 -c 参数先清空之前的结果。
allure generate [path of allure result]
# 打开已经生产的测试报告:这个命令则会启动一个 Web 服务将打开。

在这里插入图片描述
在这里插入图片描述

3. mockito

mockito可以模拟真实环境,Mock测试就是在测试的过程中,对于某些不容易构造的,如HttpServletRequest必须在Servlet容器中才能构造出来,或者不容易获取比较复杂的对象(如JDBC中的ResultSet对象),用一个虚拟的对象(Mock对象)来创建以便测试的测试方法

Mock最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,他能帮你模拟这些依赖,并帮你验证所调用的依赖的行为

import org.junit.Test;

import java.util.LinkedList;
import static org.mockito.Mockito.*;


public class test {
    LinkedList linkedList =  mock(LinkedList.class);
    @Test
    public void test(){
        //创建linkedlist

        System.out.println(linkedList.get(0)); //null
    }

    //方法调用的方绘制
    @Test
    public void test2(){ //模拟方法的调用的返回值
        when(linkedList.get(0)).thenReturn("first"); //当调用get(0)是返回first
        System.out.println(linkedList.get(0)); //输出first
    }

    //方法调用抛出异常
    //模拟获取第二个元素时,抛出runtimeException
    @Test
    public void test3(){
        when(linkedList.get(1)).thenReturn(new RuntimeException());
        System.out.println(linkedList.get(1));
    }

    //调用方法时的参数匹配
    @Test
    public void test4(){
        when(linkedList.get(anyInt())).thenReturn("element");
        System.out.println(linkedList.get(100)); //返回element -任意index都会返回element
    }
    ```
;