junit

第五十四章 单元测试框架JUnit

1. 简介

JUnit是一款常用于Java工程的开源单元测试框架(Open Source Unit Test Framework)。软件测试大致可在三个层次上进行。系统测试(System Test)用于测试整个系统的功能;集成测试(Integration Test)用于测试两个或者多个子模块集成之后的功能;单元测试(Unit Test)用于测试系统中每个最小单元的功能。因此,从上述的测试目的和定义来看,单元测试的对象是项目中最小的、不可再分的单元。在Java项目中,单元测试的对象是一个个独立的类。单元测试一般由开发人员维护和执行。测试人员一般不执行单元测试。

JUnit 5由三个模块组成。JUnit Platform模块提供了测试基础功能和服务。JUnit Jupiter模块提供了测试框架模型与测试扩展模型。在本章中的例子都是使用JUnit Jupiter完成的。JUnit Vintage提供了向后兼容(Backward Compatibility);开发人员可在JUnit 5中运行JUnit 3和JUnit 4的测试用例(Test Cases)。

如果在Maven项目中使用JUnit 5的话,需要在pom.xml中添加如下依赖。

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

如果在Gradle项目中使用JUnit 5的话,需要在build.gradle中添加如下依赖。

repositories {
	mavenCentral()
}

dependencies {
	testImplementation('org.junit.jupiter:junit-jupiter:5.7.0')
}

2. 使用方法

2.1 功能代码(被测试的代码)

为了展示JUnit 5的用法,我们将使用JUnit 5来测试下面的功能代码。这段代码实现了一个斐波那契数列生成器。当创建一个FibonacciGenerator对象之后,通过调用get()方法能够生成相应的斐波那契数。

package com.littlewaterdrop;

public class FibonacciGenerator {
    public int get(int i) throws IllegalArgumentException {
        if (i < 0) {
            throw new IllegalArgumentException();
        } else if (i == 0) {
            return 0;
        } else if (i == 1) {
            return 1;
        } else {
            return this.get(i-2) + this.get(i-1);
        }
    }

    public static void main(String[] args) {
        FibonacciGenerator fibonacciGenerator = new FibonacciGenerator();
        for (int i = 0; i < 10; i++) {
            System.out.println(String.format("Fibonacci(%d) = %d", i, fibonacciGenerator.get(i)));
        }
    }
}

上述的代码输出如下结果。

Fibonacci(0) = 0
Fibonacci(1) = 1
Fibonacci(2) = 1
Fibonacci(3) = 2
Fibonacci(4) = 3
Fibonacci(5) = 5
Fibonacci(6) = 8
Fibonacci(7) = 13
Fibonacci(8) = 21
Fibonacci(9) = 34

2.2 测试代码结构

无论是Maven项目还是Gradle项目,项目中的测试代码结构是相同的。例如,在如下的项目中,功能代码放在src/main/java目录下。源代码按照其包(package)的结构存放在相应的目录下。因此,FibonacciGenerator.java存放在src/main/java/com/littlewaterdrop目录下。

单元测试的代码存放在src/test/java目录下。通常的做法是按照功能代码的结构来组织单元测试代码,并且单元测试类与被测试类应一一对应,并按照其包的结构安排。例如,FibonacciGenerator.java放在com.littlewaterdrop包中。那么,测试FibonacciGenerator的单元测试类可命名为FibonacciGeneratorTest,存放在com.littlewaterdrop目录下。

以此类推,如果我们有一个新类com.littlewaterdrop.util.StringUtil,那么,它的单元测试类可命名为StringUtilTest,放在包com.littlewaterdrop.util中。

注意,上述仅仅是一种常见的、惯用的方法。开发人员也可以按照自己的喜好和习惯安排组织单元测试代码。

A-Java-Project
 |- src
 |  |- main
 |  |  |- java
 |  |  |  |- com
 |  |  |  |  |- littlewaterdrop
 |  |  |  |  |  |- FibonacciGenerator.java
 |  |- test
 |  |  |- java
 |  |  |  |- com
 |  |  |  |  |- littlewaterdrop
 |  |  |  |  |  |- FibonacciGeneratorTest.java

2.3 JUnit测试执行周期

在执行单元测试的过程中,因为每个单元测试类都是相互独立的。因此,单元测试的结果应不依赖于其执行顺序。所以,在默认情况下,JUnit会按照某一内部顺序依次执行每一个测试类。类似的,在一个测试类中,每个测试用例也应是相互独立的,JUnit也会按照某一内部顺序依次执行测试类中的每一个测试用例。

在执行一个测试类时,JUnit会创建新对象来执行每一个测试用例。换句话说,在调用测试函数之前,JUnit会创建出一个新的测试类对象。然后,在这个新的对象上调用测试函数。这样做的目的是隔离(Isolation)测试用例的副作用(Side Effect),避免一个测试用例的行为影响另一个测试用例的测试结果。

开发人员可以为每一个测试类设置BeforeAll方法、BeforeEach方法、AfterAll方法和AfterEach方法。BeforeAllAfterAll方法是测试类的静态方法。JUnit会在执行这个测试类之前和完毕之后分别调用这两个方法。BeforeEachAfterEach方法是测试类的成员方法。JUnit会在执行每一个测试用例之前和完毕之后分别执行这两个方法。因此,BeforeAllAfterAll最多只会执行一次;而BeforeEachAfterEach可能会支持多次。

2.4 JUnit测试用例

下面是测试FibonacciGenerator的单元测试类FibonacciGeneratorTest。它使用了标注(Annotation)来标记BeforeAllAfterAllBeforeEachAfterEach方法。在BeforeEach方法中,每次创建一个新的FibonacciGenerator对象。

FibonacciGeneratorTest类还包含了两个测试用例:testFibonacciOfZero()和testFibonacciOfOne()方法。它们分别测试Fibonacci(0)和Fibonacci(1)的值。这两个方法使用了@Test标注来将自己标识为测试用例。因此,JUnit在运行此测试类时,会运行这两个测试用例。

在测试用例中,开发人员需要使用assert*()方法来检查测试的结果。如果所有的assert()方法全部通过的话,则该测试用例会被认为测试通过。如果当有任何一个assert()方法失败时,该测试用例会被认为失败。

assert*()方法是类org.junit.jupiter.api.Assertions的静态成员方法。所以,开发人员可以使用import static语句将它们导入进来。在使用时,可以直接使用方法名称调用assert*()方法。

import static org.junit.jupiter.api.Assertions.assertEquals;
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.DisplayName;
import org.junit.jupiter.api.Test;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeAll
    static void initAll() {
    }

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @DisplayName("Test Fibonacci(0)")
    void testFibonacciOfZero() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @DisplayName("Test Fibonacci(1)")
    void testFibonacciOfOne() {
        assertEquals(1, fibonacciGenerator.get(1));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }

    @AfterAll
    static void tearDownAll() {
    }
}

在上述的测试用例中,我们测试了Fibonacci(0)和Fibonacci(1)的值是否为0和1。标注@DisplayName可用于在测试报告中输出个性化的测试用例信息。

2.5 更多的assert*()方法

JUnit提供了许多方便的assert*()方法。例如,assertEquals()用于比较两个对象是否相等。更多的assert*()方法如下表所示。

方法描述
assertEquals()断言给定的两个对象相等。
assertTrue()断言给定的条件为true。
assertFalse()断言给定的条件为false。
assertNull()断言给定的对象引用为null。
assertNotNull()断言给定的对象引用不为null。
assertSame()断言给定的两个对象引用指向同一个对象。
assertNotSame()断言给定的两个对象引用指向不同的对象。
assertArrayEquals()断言给定的两个数组相等。
assertAll()断言给定的所有条件全部为true。
assertTimeout()断言给定的任务执行时间不超过指定的时间。
assertThrow()断言给定的任务会抛出指定的异常。
fail()直接判定测试用例失败。

所以,我们可以在测试代码中使用上述的assert*()方法来检验测试结果。

import static org.junit.jupiter.api.Assertions.*;
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.DisplayName;
import org.junit.jupiter.api.Test;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeAll
    static void initAll() {
    }

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @DisplayName("Test Fibonacci(0)")
    void testFibonacciOfZero() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @DisplayName("Test Fibonacci(0)、Fibonacci(1)、Fibonacci(2)")
    void testFibonacciOfZeroOneTwo() {
        assertAll(
            () -> assertEquals(0, fibonacciGenerator.get(0)),
            () -> assertEquals(1, fibonacciGenerator.get(1)),
            () -> assertEquals(1, fibonacciGenerator.get(2))
        );
    }

    @Test
    @DisplayName("Test Speed of Fibonacci(0)")
    void testSpeedOfFibonacci() {
        // 当任务没有返回值时
        assertTimeout(
            java.time.Duration.ofSeconds(1), 
            () -> fibonacciGenerator.get(0)
        );

        // 当任务有返回值时
        int result = assertTimeout(
            java.time.Duration.ofSeconds(1), 
            () -> { return fibonacciGenerator.get(1);}
        );
        assertEquals(1, result);
    }

    @Test
    @DisplayName("Test invalid parameter")
    void testFibonacciOfInvalidParameter() {
        assertThrows(IllegalArgumentException.class, () -> fibonacciGenerator.get(-1));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }

    @AfterAll
    static void tearDownAll() {
    }
}

2.6 JUnit Assumption (预设条件)

JUnit还提供了预设条件系列函数assume*()。有时,一些测试用例只有在一定的运行环境和条件下运行才有意义。那么,开发人员可以使用assume*()函数来检查运行环境和条件。

开发人员往往容易混淆assume*()函数和assert*()函数,因为它们有着十分相似的接口,并且都可用于测试用例函数中。一旦测试失败,JUnit会终止执行当前的测试用例。但是,它们有着本质的区别。assume*()用于检查预设条件,当条件不满足时,JUnit会跳过当前测试用例。具体的说,当assume*()函数断言失败后,JUnit会跳出当前的测试用例;当前的测试用例不会认为是失败的。然而,当assert*()函数断言失败后,该测试用例会被认为是失败的。这是assume*()与assert*()函数最重要的区别。

我们使用如下的例子来解释如何使用assume*()。我们假设只需要测试0-10以内整数的斐波那契的值。所以,在testFibonacci()测试用例中,我们先使用assumeTrue()测试变量i的值。如果i的值不在[0, 10]之内,那么就不执行该测试用例。

assume*()方法是类org.junit.jupiter.api.Assumptions的静态成员方法。所以,开发人员可以使用import static语句将它们导入进来。在使用时,可以直接使用方法名称调用assume*()方法。

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

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

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private int i;
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        i = 0;
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @DisplayName("Test Fibonacci(0) to Fibonacci(10)")
    void testFibonacci() {
        assumeTrue(this.i >= 0 && this.i <=10);
        assertEquals(0, fibonacciGenerator.get(this.i));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}

2.7 条件执行(Conditional Test Execution)

JUnit还支持根据外部条件来选择运行测试用例。

2.7.1 根据操作系统环境选择测试用例

开发人员可以使用@EnabledOnOs和@DisabledOnOs标注来根据操作系统类型来选择运行测试用例。例如,testOnlyOnLinux()测试用例仅在Linux环境下运行。testNotOnWindows()测试用例不会在Windows上运行。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @EnabledOnOs(OS.LINUX) // 仅在Linux环境下运行
    void testOnlyOnLinux() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @EnabledOnOs({OS.LINUX, OS.MAC}) // 仅在Linux或者Mac环境下运行
    void testOnlyOnLinuxOrMac() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @DisabledOnOs(OS.WINDOWS) // 不在Windows环境下运行
    void testNotOnWindows() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}
2.7.2 根据Java运行环境选择测试用例。

开发人员可以使用@EnabledOnJre和@DisabledOnJre标注来根据Java运行环境来选择运行测试用例。例如,testOnlyOnJava8()测试用例仅在Java 8环境下运行。testNotOnJava9()测试用例不在Java 9环境下运行。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.condition.EnabledOnJre;
import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.condition.EnabledForJreRange;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }
    
    @Test
    @EnabledOnJre(JRE.JAVA_8) // 只在JAVA 8环境下执行
    void testOnlyOnJava8() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @EnabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_14) // 只在JAVA 8至JAVA 14环境下执行
    void testOnlyOnJava8To11() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @EnabledForJreRange(min = JRE.JAVA_8) // 只在JAVA 8或之上的环境下执行
    void testOnlyOnJava8OrAbove() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @DisabledOnJre(JRE.JAVA_9) // 不在Java 9的环境下执行
    void testNotOnJava9() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}
2.7.3 根据系统变量的值选择测试用例。

开发人员可以使用@EnabledIfSystemProperty和@DisabledIfSystemProperty标注来根据系统属性的值来选择运行测试用例。在Java应用程序中,系统属性可以通过System.getProperty()和System.setProperty()来设置和获取。如下面的代码所示,onlyOn64BitArchitectures()测试用例仅在系统变量os.arch包含字符串"64"时才运行。当os.arch包含字符串"32"时,不会运行notOn32BitArchitectures()测试用例。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")
    void onlyOn64BitArchitectures() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @DisabledIfSystemProperty(named = "os.arch", matches = ".*32.*")
    void notOn32BitArchitectures() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}
2.7.4 根据环境变量的值选择测试用例。

开发人员可以使用@EnabledIfEnvironmentVariable和@DisabledIfEnvironmentVariable标注来根据环境属性的值来选择运行测试用例。在Java应用程序中,环境属性可以通过System.getEnv()来获取。如下面的代码所示,onlyOnDevelopmentServer()测试用例仅在环境变量ENV为字符串"developemnt"时才运行。当环境变量ENV包含字符串"Production"时不执行notOnProductionServer()测试用例。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @EnabledIfEnvironmentVariable(named = "ENV", matches = "development")
    void onlyOnDevelopmentServer() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @DisabledIfEnvironmentVariable(named = "ENV", matches = ".*Production.*")
    void notOnProductionServer() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}
2.7.5 根据自定义逻辑选择测试用例。

开发人员还可以使用@EnabledIf和@DisabledIf标注来自定义逻辑选择运行测试用例。如下面的代码所示,开发人员可以将自定义的逻辑写入一个成员方法中,该方法的返回值为boolean类型。JUnit会根据该成员函数的返回值来判断是否运行测试用例。例如,在下面的代码中,JUnit会根据成员函数customCondition()的返回值来选择是否运行enabled()和disabled()测试用例。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.condition.DisabledIf;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @EnabledIf("customCondition")  // 当函数customCondition()返回true时运行
    void enabled() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @DisabledIf("customCondition")  // 当函数customCondition()返回true时不运行
    void disabled() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    public boolean customCondition() {
        return true;
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}

2.8 测试用例执行顺序 (The Order of Execution)

开发人员可以使用@Order标注来明确指定某一测试类中的测试用例的执行顺序。例如,在如下的代码中,firstTestCase()会在secondTestCase()之前运行。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.TestMethodOrder;

import com.littlewaterdrop.FibonacciGenerator;

@TestMethodOrder(OrderAnnotation.class)
@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @Order(10)
    void firstTestCase() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @Test
    @Order(20)
    void secondTestCase() {
        assertEquals(1, fibonacciGenerator.get(1));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}

2.9 重复运行测试用例

@RepeatedTest标注允许开发人员反复运行某一测试用例。在下面的示例中,repeatThisTestcase10Times()测试用例会运行10次。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @RepeatedTest(10)
    void repeatThisTestcase10Times() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}

2.10 超时

@Timeout标注允许开发人员为测试用例设置一个超时时间。如果运行超时,该测试用例会被记录为失败。@Timeout与assertTimeout()方法不同之处在于,@Timeout设置的是整个测试用例的超时时间,而assertTimeout()方法设置的是一个具体执行过程或者步骤的超时时间。

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.DisplayName;
import java.util.concurrent.TimeUnit;

import com.littlewaterdrop.FibonacciGenerator;

@DisplayName("Test FibonacciGenerator")
public class FibonacciGeneratorTest {
    private FibonacciGenerator fibonacciGenerator = null;

    @BeforeEach
    void init() {
        fibonacciGenerator = new FibonacciGenerator();
    }

    @Test
    @Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
    void failsIfExecutionTimeExceeds100Milliseconds() {
        assertEquals(0, fibonacciGenerator.get(0));
    }

    @AfterEach
    void tearDown() {
        fibonacciGenerator = null;
    }
}

3 小结

本章介绍了JUnit框架的使用方法。JUnit是一款流行的Java应用程序的单元测试框架,它主要以类为单位测试Java代码的功能。为了更好的完成单元测试,开发人员往往会在单元测试中使用Mock技术,以覆盖更多的测试场景。因此,我们将在下一章中介绍与JUnit结合使用的Mock框架。

上一章
下一章

注册用户登陆后可留言

Copyright  2019 Little Waterdrop, LLC. All Rights Reserved.