JUnit 是一个 Java 编程语言的开源测试框架,它是xUnit架构的一部分,xUnit是为多种编程语言创建的单元测试库的通用名称。JUnit是由Erich Gamma和Kent Beck创建的,目前已经发展到JUnit 5。
它提供了一些功能,使编写测试变得容易,包括支持多个测试用例、断言和报告。JUnit也是多功能的,允许用各种语言编写测试。
JUnit 主要用于单元测试,但它也可用于其他测试,如功能和集成测试。功能测试是测试系统的功能。它们与单元测试不同,因为它们测试的是整个系统而不是单个单元。集成测试测试两个或多个系统的集成。它们与单元测试不同,因为它们测试的是系统的各个组成部分如何协同工作,而不是单独工作。
对于单元测试框架来讲,它主要完成以下几件事。
提供用例组织与执行: 测试用例只有几条时,可以不考虑用例组织,但是用例达到成百上千时,大量的测试用例堆砌在一起,就产生了扩展性与维护性等问题
提供丰富的断言方法: 不论是功能测试,还是单元测试,在用例执行完之后都需要将实际结果与预期结果相比较(断言),从而断定用例是否执行通过。单元测试框架一般提供丰富的断言方法。例如:判断相等/不等、包含/不包含、True/False的断言方法等
提供丰富的日志: 当测试用例执行失败时能抛出清晰的失败原因,当所有用例执行完成后能提供丰富的执行结果。例如,总执行时间、失败用例数、成功用例数等。
从这些特性来看单元测试框架的作用是:帮助我们更自动化完成测试,所以,它是自动化测试的基础。
在平时的开发当中,一个项目往往包含了大量的方法,可能有成千上万个。如何去保证这些方法产生的结果是我们想要的呢?当然了,最容易想到的一个方式,就是我们通过 System.out 来输出我们的结果,看看是不是满足我们的需求,但是项目中这些成千上万个方法,我们总不能在每一个方法中都去输出一遍嘛。这也太枯燥了。这时候用我们的单元测试框架JUnit就可以很好地解决这个问题。
JUnit 如何解决这个问题的呢?答案在于内部提供了一个断言机制,他能够将我们预期的结果和实际的结果进行比对,判断出是否满足我们的期望。
JUnit主要用于单元测试,以下是JUnit的主要用途:
- 编写和运行测试: JUnit提供了注解和断言库,帮助你快速地编写测试代码,并且提供了测试运行器来运行和报告测试结果。
- 断言结果: JUnit提供了一套丰富的断言库来帮助你验证测试的结果。这些断言方法包括常用的 assertEquals、assertTrue、assertFalse、assertNull 等。
- 测试套件: 如果你有一组测试,并希望将它们一起运行,那么可以使用 JUnit 的 @TestSuite 注解。
- 测试异常: JUnit 可以帮助你测试方法是否会抛出预期的异常。
- 参数化测试: 如果你需要使用不同的参数多次运行同一个测试,那么可以使用 JUnit 的参数化测试。
- 模拟对象: 在很多情况下,你可能需要模拟依赖对象以便于测试。JUnit 可以与模拟框架(如Mockito)一起使用,帮助你创建模拟对象。
总的来说,JUnit是Java中非常重要的一个单元测试框架,它的使用可以使你的代码更加健壮,因为你可以快速定位并修复代码中的错误和bug。
Junit目前分两个版本,Junit4 和 Junit5 , 本系列教程打算从 Junit4 开始介绍,最后,再介绍 Junit5 有哪些新特性
推荐使用 IntelliJ IDEA
- 下载 junit-4.12.jar 文件:https://github.com/junit-team/junit4/releases
- 打开 IntelliJ IDEA ,菜单栏:File菜单 Porject Structure 选项 modules
Dependencies 标签 点击 “+” 号 Library Java 。
如果是 Maven 项目,可通过如下进行下载:
访问 jar 包查询网站: https://mvnrepository.com/
搜索 junit ,并选择最多的人的一个版本,添加到 中,如:
在 JUnit 中,模拟(Mocking)和存根(Stubbing)是测试中常用的技术,可将被测代码与其依赖项隔离开来,并在受控环境中模拟真实世界对象的行为。这种隔离(尤其是在复杂的应用程序中)可确保测试仅关注被测单元的功能,而不是任何外部依赖项。
一个外部依赖项: 指的是系统中的一个对象,被测试的代码与这个对象发生交互,但是你不能控制这个对象。比喻前端工程师和后台工程师合作,前端工程师要等待后台返回的数据来处理,那么后台就是他的一个外部依赖项。因为他无法控制后台的代码
- 模拟是指创建一个模拟对象来替代真实的依赖项对象,并模拟其行为。模拟对象通常是使用特殊的框架(如Mockito、EasyMock等)生成的,它们可以模拟外部依赖项的方法调用和返回值,以及对方法的预期行为进行验证。通过模拟对象,可以模拟复杂的环境和各种测试情况,以便更容易地进行单元测试,同时解耦被测代码与外部依赖项的耦合性。
模拟对象是伪对象,它可以验证被测试对象是否按照预期的方式调用了这个伪对象,因此来判断单元测试的成功或者失败。
举一个例子: 小明由于作业没有做完,老师就让小明放学之后晚回家一个小时来写作业,那么今天老师有事就提前回家了,就让班长小亮来查看小明是否留下来一个小时在写作业。此时小亮就是我们说的伪对象,他就检测了小明是否晚回家一个小时。
- 存根是指为外部依赖项提供固定的返回值或行为,以便在测试过程中控制其行为。存根对象通常是手动创建的,并在测试中替换真实的依赖项对象。通过存根,可以控制外部依赖项的返回结果,以确保测试的可重复性和可预测性。存根可以返回预先定义的结果,模拟异常,或者执行自定义的行为。
一个存根(stub)是对系统中存在的一个依赖项(或协作者)的可控制的替代物(就是你找一个对象来替换你无法控制的对象)。通过使用存根,你在测试代码时无需直接处理这个依赖项。(说白了就是一个你自己定义对象来取代你无法控制的对象)
这些技术可以用于创建更可靠和独立的单元测试,使测试更加可控和可预测。它们有助于隔离被测代码和外部依赖项之间的交互,并使测试更专注于被测代码本身。
6.1 使用模拟和存根的例子
下面,使用JavaScript中的流行测试库,Jest,来展示如何使用模拟和存根。
例1:使用存根
假设你有一个函数 getUserName,它从数据库中获取用户的名字。你想要测试这个函数,但是不想依赖真实的数据库。
可以使用 Jest 的 方法来创建一个存根:
在这个例子中,我们创建了一个存根来代替 db.getUser 方法。这个存根总是返回一个具有名字 “Alice” 的用户。
例2:使用模拟
假设有一个 login 函数,它调用了一个 authentication 服务来验证用户的凭据。想要测试这个函数,但是更关心它是否正确地调用了 authentication 服务。
可以使用 Jest 的 jest.fn() 方法来创建一个模拟:
在这个例子中,我们创建了一个模拟来代替 方法。然后,我们使用 方法来验证 函数是否正确地调用了 方法。
结论
模拟和存根是单元测试中的重要工具。它们帮助我们创建隔离的测试环境,使我们能够集中测试代码的特定部分,而不必担心其他外部依赖项。
6.2 手工模拟对象和存根存在的问题
- 编写模拟对象和存根耗时间
- 如果接口有很多方法、属性、事件编写的时候会特别困难
- 如果验证调用者向另一个方法调用传递的所有参数都是正确的时候就需要多次进行断言。
- 有些模拟对象就是为特定的方法编写复用性比较差
创建一个简单的Java类,这个类将包含一些基础的数学运算。这个类名叫做Calculator:
这个类包含四个方法,分别实现加法、减法、乘法和除法运算。注意,在进行除法运算时,我们需要检查除数是否为0,如果是0,我们抛出一个 异常。
接下来,我们将为这个类创建一个 JUnit 测试类,以测试它的功能。
测试代码
在中,通常会为要测试的类创建一个同名的测试类,只不过这个测试类的名字后面会附加。为类创建一个名为的测试类。
这个测试类中,会为类中的每个方法都编写一个对应的测试方法。使用注解来标识这些测试方法。
下面是类的代码:
在这个类中,首先定义了一个私有的 实例,然后在 注解的 方法中为它赋值。 注解的方法会在每个测试方法运行前被调用,所以可以在这里初始化测试环境。
然后为类中的每个方法都编写了一个测试方法。在这些测试方法中,使用了方法来检查方法的返回值是否和我们预期的一样。
对于方法,还写了一个额外的测试方法来测试当除数为时,方法是否会抛出异常。使用方法来检查这个异常是否被正确地抛出。
接下来,可以右击IDEA中的测试类或者测试方法,然后选择 “Run ‘test…’” 来运行测试。,可以看到测试全部通过
以上就是单元测试,需要遵循以下规则:
- 每一个测试方法上使用 进行修饰
- 每一个测试方法必须使用 进行修饰(即 public 且不返回任何值)
- 每一个测试方法不能携带参数
- 测试代码和源代码在两个不同的项目路径下
- 测试类的包应该和被测试类保持一致
- 测试单元中的每个方法必须可以独立测试
以上的 6 条规则,是在使用单元测试的必须项,当然JUnit也建议在每一个测试方法名加上 前缀,表明这是一个测试方法。
是一个断言的规则,里面有两个参数,第一个参数表明预期的值,第二个参数表示实际运行的值。不过 对这些做出了一些改变,会在后续专门介绍。
运行测试类,就会运行每一个测试方法,也可以运行某一个,只需要在相应的测试方法上面右键运行即可。如果运行成功编辑器的控制台不会出现错误信息,如果有就会出现 等信息。
@Test注解有两个可选的参数:
expected 表示此测试方法执行后应该抛出的异常,
timeout 检测测试方法的执行时间 2 @BeforeAll(JUnit 5)/ @BeforeClass(JUnit 4) 在所有测试方法运行前,被执行一次。
注意,这个注解标注的方法必须是静态的。public static void 3 @BeforeEach(JUnit 5)/ @Before(JUnit 4) 在每一个测试方法运行前,被执行。
在需要为每个测试方法做一些准备工作,如初始化一些公共的变量或对象时,会非常有用。
注意必须是public void,不能为static 4 @AfterEach(JUnit 5)/ @After(JUnit 4) 在每一个测试方法运行后,被执行。
需要在每个测试方法后做一些清理工作时,会非常有用。
注意必须是public void,不能为static 5 @AfterAll(JUnit 5)/ @AfterClass(JUnit 4) 在所有测试方法运行后,被执行一次。
这对于一次性的清理工作,如关闭数据库连接,很有用。
注意,这个注解标注的方法必须是静态的。public static void 6 @Ignore 表示该测试方法被忽略,即在运行测试时,这个方法不会被执行。
可以为这个注解提供一个可选的参数说明为什么这个测试方法被忽略。 7 @ParameterizedTest(JUnit 5) 用于表示一个参数化的测试方法。与之配合使用的还有一些注解,如
@ValueSource、@EnumSource、@MethodSource、@CsvSource等,
它们用于提供测试数据。 8 @RunWith
- 与@BeforeClass的区别在于,@Before不止运行一次,它会在每个用例运行之前都运行一次。
- 每个测试用例的运行次序,即:

Arithmetic.java,本例要用到的需要Junit进行单元测试的类:
ArithmeticTest.java,Arithmetic.java的Junit单元测试类:
样例日志输出:
创建被测试类 Count .
创建测试类 CountTest .
- 在 testAdd() 用例中设置 , 说明用例的运行时间不能超过 100 毫秒, 但故意在用例添加 方法休眠 101 毫秒,所以会导致用例失败。
- 在 Java 中被除数不能为0,所以 会报 异常, 在 中设置 ,说明抛该异常符合预期。
- 表来标识该用例跳过,不管用例运行成功还是失败。
执行结果如下:
在一个单元测试中,经常编写多个 方法,来分组、分类对目标代码进行测试。
在测试的时候,经常遇到一个对象需要初始化,测试完可能还需要清理的情况。如果每个方法都写一遍这样的重复代码,显然比较麻烦。
JUnit 提供了编写测试前准备、测试后清理的固定代码,称之为 。(及 Junit 4 注解案例 1)
因此,总结出编写的套路如下:
- 对于实例变量,在中初始化,在中清理,它们在各个方法中互不影响,因为是不同的实例;
- 对于静态变量,在中初始化,在中清理,它们在各个方法中均是唯一实例,会影响各个方法。
大多数情况下,使用和就足够了。只有某些测试资源初始化耗费时间太长,以至于不得不尽量“复用”时才会用到和。
最后,注意到每次运行一个方法前,JUnit 首先创建一个 实例,因此,每个方法内部的成员变量都是独立的,不能也无法把成员变量的状态从一个方法带到另一个方法。
如果待测试的输入和输出是一组数据: 可以把测试数据组织起来 用不同的测试数据调用相同的测试方法
参数化测试和普通测试稍微不同的地方在于,一个测试方法需要接收至少一个参数,然后,传入一组参数反复运行。
JUnit 提供了一个 注解,用来进行参数化测试。
可以使用 或 或 或 ,来分别从值类型、枚举类型、方法类型、外部csv文件类型来传入所有你要测试的所有数据。下面就介绍下这几种注解的参数化测试使用方法。
1. 值类型
- short (使用 shorts )
- byte (使用 bytes )
- int (使用 ints )
- long (使用 longs )
- float (使用 floats )
- double (使用 doubles )
- char (使用 chars )
- java.lang.String (使用 strings )
- java.lang.Class (使用 classes )
假设想对 进行测试,先用一组正数进行测试:
再用一组负数进行测试:
注意到参数化测试的注解是,而不是普通的。
实际的测试场景往往没有这么简单。假设自己编写了一个方法,它会把字符串的第一个字母变为大写,后续字母变为小写:
要用参数化测试的方法来测试,不但要给出输入,还要给出预期输出。因此,测试方法至少需要接收两个参数:
现在问题来了:参数如何传入?
2. 方法类型
最简单的方法是通过注解,它允许编写一个同名的静态方法来提供测试参数:
上面的代码很容易理解:静态方法返回了一组测试参数,每个参数都包含两个,正好作为测试方法的两个参数传入。
如果静态方法和测试方法的名称不同, 也允许指定方法名。但使用默认同名方法最方便。
3. 外部 csv 文件类型
另一种传入测试参数的方法是使用 ,它的每一个字符串表示一行,一行包含的若干参数用,分隔,因此,上述测试又可以改写如下:
如果有成百上千的测试输入,那么,直接写就很不方便。这个时候,我们可以把测试数据提到一个独立的文件中,然后标注上:
只在 中查找指定的 文件,因此, 这个文件要放到 目录下,内容如下:
在 项目中,在 资源文件夹下新建 文件,内容如下:
下面的测试方法将读取文件的每一行,每次传入这三个参数进行测试。
是跳过文件第1的标题(如果你的csv文件没有标题可去除属性)
4. 枚举类型
单元测试方法:
测试结果:
如果你不想测试Month类里的所有枚举。只想测试Month类里的三月和五月,可以使用names来过滤出它们进行测试
首先要分清几个概念: 测试方法、测试类、测试集、测试运行器。
其中测试方法就是用注解的一些函数。测试类是包含一个或多个测试方法的一个文件,测试集是一个 ,可能包含多个测试类。测试运行器则决定了用什么方式偏好去运行这些测试集/类/方法。
JUnit 用例都是在 (运行器)来执行的。通过它,可以为这个测试类指定一个特定的 。那么大多数时候都没有使用 这个注解,这是为什么呢?其实, 中有一个默认的 ,它的名字叫 ,但这是在JUnit4.4之后才引入的,对于4.4之前版本的JUnit,它的名字叫 。
写过关于Spring项目的单元测试的同学可能见过这样的写法,就是用JUnit加载Spring的配置文件以完成Context的初始化,然后从Context中取出Bean并完成测试:
注意这里使用了注解,表明这个类中的测试用例需要使用类来执行。
就是放在测试类名之前,用来确定这个类怎么运行的。也可以不标注,会使用默认运行器。
常见的运行器有:
1. : 参数化运行器,配合 使用 JUnit 的参数化功能
类是 自带的,用于使用多个参数组合多次执行同一个测试用例。看下面的例子:
可以看到,虽然 类中只有两个测试用例 和 ,但是结果输出了 8 行,即每个用例都执行了 4 遍。
使用注解需要注意几点:
- 该方法要有构造函数
- 有一个的方法被标注,并且该方法只能返回类型或数组类型的数据(源代码是如下处理的)
因为上面的方式使用了构造方法来初始化数据,其实也可以使用字段注入来代替构造方法,只需稍加改变类即可:
- 用参数来修饰属性。注意:索引从0开始
- 属性要用修饰
2. 测试套件
其作用是使用 执行一个测试套件。 类是 自带的,意为套件,顾名思义,就是一套东西。通过它,可以把多个相关的测试类看做一个测试套件一起测试。看个例子:
指定了 类,说明这个 类是一个套件。通过指定了要执行的测试类(这些类中的所有用例都会执行)。
需要注意的是,这个类本身用例则不会执行了(如上面的方法)。
3.
顾名思义,执行一个 “类别”。和 类似,只是 是执行指定类中的所有用例,而 执行的范围更小,是在 的基础上只执行指定的“类别”的用例。这就需要事先在各个测试用例上用 标注该用例属于那些“类别”,之后便可以通过类别来选择执行某些用例。看例子:
其中, 和 代表两个不同的“类型”, 类中通过标注了各个用例(可以为一个用例指定多个 ,例如上方的 方法)。 指明了需要执行的类型,而 指明了不希望执行的类型,这个注解对于过滤类似这样有多个类型的用例很有效。以下是执行结果:
可以看到,只有标注了的用例执行了,而且带有的则被过滤掉了,所以只剩下这一个用例了。
4.
提供一组参数的排列组合值作为待测方法的输入参数。同时注意到在使用 这个 的时候,我们的待测方法可以拥有输入参数,而这在其它的 中的测试方法是不行的。下面是一个例子:
上面的代码的意思是,将 四个参数以类型合法的排列组合传给待测方法。因此输出的结果必然也有 种。下面是执行结果:
不过,为了简单,我们除了可以使用 注解来提供参数之外,还可以通过@DataPoints注解来提供参数,参照上述代码,只需要将注解标注的四个字段参数替换为如下的两个即可:
在运行测试的过程中,有时候需要控制各测试用例的执行顺序。
@FixMethodOrder
JUnit 通过 @FixMethodOrder 注解来控制测试方法的执行顺序的。@FixMethodOrder 注解的参数是 org.junit.runners.MethodSorters 对象,在枚举类 org.junit.runners.MethodSorters 中定义了如下三种顺序类型:
Leaves the test methods in the order returned by the JVM. Note that the order from the JVM may vary from run to run (按照JVM得到的方法顺序,也就是代码中定义的方法顺序)- (默认的顺序)
Sorts the test methods in a deterministic, but not predictable, order() (以确定但不可预期的顺序执行)
Sorts the test methods by the method name, in lexicographic order, with Method.toString() used as a tiebreaker (按方法名字母顺序执行)
具体如何使用,看例子,创建 TestRunSequence 测试类。
设置按字母的顺序执行,所以, 先被执行,虽然它在代码中是最后一条用例。
断言就是专门用来验证输出和期望是否一致的一个工具。换句话说断言就是判断一个方法所产生的结果是否符合你期望的那个结果。
例如assertEquals(5, calculator.add(2, 3))会检查calculator.add(2, 3)的返回值是否为5。 2 assertNotEquals(first, second, message) 如果预期值 expected 等于实际返回值 actual ,则断言失败。 3 assertArrayEquals(expecteds, actuals, message) 如果两个数组不相等,则断言失败 4 assertIterableEquals(Iterable1,Iterable2, message) 如果两个列表集合的元素顺序或大小不相等,则断言失败 5 assertTrue(booleanExpression, message) 如果 booleanExpression 不是 true ,则断言失败。 6 assertFalse(booleanExpression, message) 如果 booleanExpression 不是 false ,则断言失败。 7 assertNull(actual, message) 如果 actual 不是 null ,则断言失败。 8 assertNotNull(actual, message) 如果 actual 是 null ,则断言失败。 9 assertSame(object1, object2, message) 如果两个对象引用没有指向同一个对象,则断言失败 10 assertNotSame(object1, object2, message) 如果两个对象引用指向同一个对象,则断言失败 11 assertTimeout(expectedTimeout, executable, message) 如果执行的方法超过预期的时间,则断言失败(没执行完的代码会继续执行) 12 assertTimeoutPreemptively(expectedTimeout, executable, message) 如果执行的方法超过预期的时间,则断言失败(没执行完的代码会结束执行) 12 assertThat(actual, matcher, message) 查看实际值是否满足指定的条件。 12 fail(message) 抛出异常 12
(1)message :上面这些断言方法里的 message 参数是可选的,当有 message 参数时如果断言失败时就会输出 message 内容;若没有 message 参数,断言失败则默认提示org.opentest4j.AssertionFailedError,例如:
(2)fail 断言方法:上面的最后一个 fail 断言方法用来抛出异常,使测试方法运行到 fail 方法时立即失败终止(如果是运行的整个测试类,测试类里的其他测试方法将会继续运行,只会终止当前测试方法)。fail 方法一般用于当代码执行到了某个不应该被到达的分支时使用 fail 方法终止测试方法并给出提示信息;或者在catch块中抛出异常信息。示例:
assertThat 断言是第三方库 AssertJ-core 所提供的方法,AssertJ-core 提供了一组类和实用方法,使我们能够轻松地编写流畅而漂亮的断言。
在 pom.xml 中添加 AssertJ-core 依赖:
基本语法:assertThat(参数值, 匹配符)
核心匹配
- allOf: 所有条件都必须满足,相当于 &&
- anyOf:其中一个满足就通过, 相当于 ||
- both: &&
- either: 两者之一
- everyItem: 每个元素都需满足特定条件
- hasItem: 是否有这个元素
- hasItems:包含多个元素
- is: is(equalTo(x))或is(instanceOf(clazz.class))的简写
- anything(): 任何情况下,都匹配正确
- not:否为真,相当于!
- nullValue(): 值为空
- notNullValue(): 值不为空
集合匹配
- array: 数组长度相等且对应元素也相等
- hasItemInArray: 数组是否包含特定元素
- arrayContainingInAnyOrder: 顺序无关,长度要一致
- arrayContaining: 顺序,长度一致
- arrayWithSize: 数组长度
- emptyArray:空数组
- hasSize: 集合大小
- empty: 空集合
- isIn: 是否为集合成员
collection 相关匹配符
- hasEntry
注释:hasEntry匹配符表明如果测试的Map对象mapObject含有一个键值为”key”对应元素值为”value”的Entry项则测试通过
- hasItem
注释:hasItem匹配符表明如果测试的迭代对象iterableObject含有元素“element”项则测试通过
- hasKey
注释: hasKey匹配符表明如果测试的Map对象mapObject含有键值“key”则测试通过
- hasValue
注释:hasValue匹配符表明如果测试的Map对象mapObject含有元素值“value”则测试通过
数值相关匹配符
- closeTo:[operand-error, operand+error], Double或BigDecimal类型
closeTo 匹配符表明如果所测试的浮点型数testedDouble在20.0±0.5范围之内则测试通过
- greaterThan: 大于
greaterThan 匹配符表明如果所测试的数值 testedNumber 大于 16.0 则测试通过
- lessThan: 小于
注释:lessThan匹配符表明如果所测试的数值testedNumber小于16.0则测试通过
- greaterThanOrEqualTo:大于等于
注释: greaterThanOrEqualTo匹配符表明如果所测试的数值testedNumber大于等于16.0则测试通过
- lessThanOrEqualTo: 小于等于
注释:lessThanOrEqualTo匹配符表明如果所测试的数值testedNumber小于等于16.0则测试通过
字符串相关匹配符
- containsString:包含字符串
注释:containsString匹配符表明如果测试的字符串testedString包含子字符串”developerWorks”则测试通过
- endsWith:后缀
注释:endsWith匹配符表明如果测试的字符串testedString以子字符串”developerWorks”结尾则测试通过
- startsWith:前缀
注释:startsWith匹配符表明如果测试的字符串testedString以子字符串”developerWorks”开始则测试通过
- equalTo:值相等, Object.equals(Object)
- equalToIgnoringCase:比较时,忽略大小写
注释:equalToIgnoringCase匹配符表明如果测试的字符串testedString在忽略大小写的情况下等于”developerWorks”则测试通过
- equalToIgnoringWhiteSpace:比较时, 首尾空格忽略, 比较时中间用单个空格
注释:equalToIgnoringWhiteSpace匹配符表明如果测试的字符串testedString在忽略头尾的任意个空格的情况下等
于”developerWorks”则测试通过,注意:字符串中的空格不能被忽略
- isEmptyString():空字符串
- isOneOf: 是否为其中之一
- isIn: 是否为其成员
- toString(): 返回值校验
案例
如果在测试类不断增加的情况下,如何运行所有的单元测试代码类?一个个测试类的执行吗?显然繁琐且费劲。
将要运行的测试类集成在我们的测试套件中,比如一个系统功能对应一个测试套件,一个测试套件中包含多个测试类,每次测试系统功能时,只要执行一次测试套件就可以了。
实际上就是上面注解讲到的
JUnit5 不同于之前的版本,它组合了三个子项目:
- JUnit Platform:Junit Platform是在JVM上启动测试框架的基础,不仅支持JUnit自制的测试引擎,还可以接入其他测试引擎。
- JUnit Jupiter:JUnit Jupiter提供了JUnit5新的编程模型,是JUnit5新特性的核心。内部包含了一个测试引擎,用于在JUnit Platform上运行。
- JUnit Vintage:由于JUnit已经发展多年,为了照顾老的项目,JUnit Vintage提供了兼容JUnit4和JUnit3的测试引擎。没错,只要你导入了JUnit5,也是能够使用JUnit4的注解的。

@DispalyName 给测试类和方法取名
@Disable注解
用于禁用测试类或测试方法; 类似于JUnit4的@Ignore。这个注解不能继承。
@ExtendWith
用于注册自定义扩展。 这个注解可以继承。
@RepeatedTest
表示方法是用于重复测试的测试模板。除非被覆盖,否则这些方法可以继承
以下示例演示了如何声明名为的测试,该测试将自动重复次。
除了指定重复次数外,还可以通过注解的属性为每次重复配置自定义显示名称。此外,显示名称可以是模式,由静态文本和动态占位符的组合而成。目前支持以下占位符:
- @RepeatedTest方法的显示名称
- 当前重复次数
- 重复的总次数
@TestFactory
表示方法是用于动态测试的测试工厂。除非被覆盖,否则这些方法可以继承
与@Test方法相比,@TestFactory方法本身不是测试用例,而是测试用例的工厂。因此,动态测试是工厂的产物。从技术上讲,@TestFactory方法必须返回DynamicNode实例的Stream,Collection,Iterable或Iterator。 DynamicNode的可实例化的子类是DynamicContainer和DynamicTest。 DynamicContainer实例由一个显示名称和一个动态子节点列表组成,可以创建任意嵌套的动态节点层次结构。然后,DynamicTest实例将被延迟执行,从而实现测试用例的动态甚至非确定性生成。
任何由@TestFactory返回的Stream都要通过调用stream.close()来正确关闭,使得使用诸如Files.lines()之类的资源变得安全。
与@Test方法一样,@TestFactory方法不能是private或static,并且可以选择声明参数,以便通过ParameterResolvers解析。
DynamicTest是运行时生成的测试用例。它由显示名称和Executable组成。 Executable是@FunctionalInterface,这意味着动态测试的实现可以作为lambda表达式或方法引用来提供。
@TestInstance
用于为被注解的测试类配置测试实例生命周期。 这个注解可以继承
@Tag
在类或方法级别声明标签,用于过滤测试; 类似于TestNG中的test group或JUnit 4中的Categories。这个注释可以在类级别上继承,但不能在方法级别上继承
实质上是个标记作用,把你想要在某种场景需要执行的方法用同个标记名标记归类,便可一键执行多个符合条件的测试用例。具体作用往下看即明白,此为可重复注解,存在多个时结合@Tags使用,可添加到类或方法上:
我们需要通过value指定一个标签名,这个标签名不能随便,有如下规则需要遵守:
- 不能为空白字符
- 去除左右空白符后不能包含空白符
- 不能包含ISO控制字符
- 不能包含JUnit保留字符:逗号[ , ]、小括号[ () ]、与号[ & ]、管道符[ | ]、惊叹号[ ! ]
@ExtendWith
用于注册自定义扩展。 这个注解可以继承。
详解介绍JUnit单元测试框架(完整版)
Java程序员必须要知道的单元测试框架Junit详解
一小时实践入门 JUnit
JUnit:完整指南
编写JUnit测试
IDEA中添加junit4的三种方法(详细步骤操作)
Java 中的单元测试:策略和工具
深入了解模拟和存根:提高单元测试质量的关键技术
模拟(mocking)和存根(stubbing)是什么
模拟对象和存根
破除依赖
Junit - 基础注解(@BeforeClass、@Before、@Test、@After、@AfterClass)
JUnit常用注解
Junit5简介和常用测试注解
JUnit高级用法之@RunWith
Junit 的 @RunWith():Runner,即Junit的运行器
JUnit 5单元测试(二)—— 断言
JUnit测试常用断言
assertThat用法看这一篇就够了!
assertThat用法
Junit4中的新断言assertThat的使用方法
Junit 5官方文档中文版 ☆☆☆☆☆
到此这篇junit怎么运行(junit fail)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rgzn-aibigd/42708.html