junit5教程
JUnit5教程 (JUnit5 Tutorial)
In this Junit tutorial, we will introduce basics of JUnit5 and its new features using examples. In Java world, JUnit is one of the popular framework used to implement unit tests against java code. JUnit primarily helps developers to test their code on the JVM by themselves.
在本Junit教程中,我们将通过示例介绍JUnit5的基础知识及其新功能。 在Java世界中,JUnit是用于对Java代码实施单元测试的流行框架之一。 JUnit主要帮助开发人员自己在JVM上测试其代码。
JUnit5架构 (JUnit5 Architecture)
JUnit平台 (JUnit Platform)
- Launches testing frameworks on the JVM 在JVM上启动测试框架
- Has TestEngine API used to build a testing framework that runs on the JUnit platform 使用TestEngine API来构建在JUnit平台上运行的测试框架
JUnit木星 (JUnit Jupiter)
- Blend of new programming model for writing tests and extension model for extensions 混合了用于编写测试的新编程模型和用于扩展的扩展模型
- Addition of new annotations like
@BeforeEach
,@AfterEach
,@AfterAll
,@BeforeAll
etc. 添加新的注释,例如@BeforeEach
,@AfterEach
,@AfterAll
,@BeforeAll
等。
JUnit复古 (JUnit Vintage)
- Provides support to execute previous JUnit version 3 and 4 tests on this new platform 提供支持以在此新平台上执行以前的JUnit版本3和4测试
JUnit Maven依赖关系 (JUnit Maven Dependencies)
To implement JUnit5 based test cases in a project, add the following dependency to the pom.xml file of the project:
要在项目中实现基于JUnit5的测试用例,请将以下依赖项添加到项目的pom.xml文件中:
- JUnit 5 Library JUnit 5库
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version> 1.1.1</version>
<scope>test</scope>
</dependency>
- JUnit5 maven surefire provider to execute the unit tests where IDE does not have JUnit5 support (if IDE has support then this point is not required) JUnit5 maven surefire提供程序在IDE不支持JUnit5的情况下执行单元测试(如果IDE支持,则不需要这一点)
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <dependencies> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-surefire-provider</artifactId> <version>1.0.2</version> </dependency> </dependencies> </plugin>
JUnit5的新功能 (JUnit5 New Features)
It requires Java 8 or higher at runtime. But one can still test code which is compiled using previous Java versions. There are various new features got introduced in it.
运行时需要Java 8或更高版本。 但是仍然可以测试使用以前的Java版本编译的代码。 其中引入了各种新功能。
JUnit注释 (JUnit Annotations)
Listed below are some commonly used annotations provided in it:
下面列出了其中提供的一些常用注释:
Annotation Description @Test Denotes a test method @DisplayName Declares a custom display name for the test class or test method @BeforeEach Denotes that the annotated method should be executed before each test method @AfterEach Denotes that the annotated method should be executed after each test method @BeforeAll Denotes that the annotated method should be executed before all test methods @AfterAll Denotes that the annotated method should be executed after all test methods @Disable Used to disable a test class or test method @Nested Denotes that the annotated class is a nested, non-static test class @Tag Declare tags for filtering tests @ExtendWith Register custom extensions 注解 描述 @测试 表示测试方法 @显示名称 声明测试类或测试方法的自定义显示名称 @BeforeEach 表示带注释的方法应在每个测试方法之前执行 @AfterEach 表示带注释的方法应在每个测试方法之后执行 @BeforeAll 表示带注释的方法应在所有测试方法之前执行 @毕竟 表示带注释的方法应在所有测试方法之后执行 @禁用 用于禁用测试类或测试方法 @嵌套 表示带注释的类是嵌套的非静态测试类 @标签 声明标签以过滤测试 @ExtendWith 注册自定义扩展 package com.journaldev; 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.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class JUnit5Sample1Test { @BeforeAll static void beforeAll() { System.out.println("**--- Executed once before all test methods in this class ---**"); } @BeforeEach void beforeEach() { System.out.println("**--- Executed before each test method in this class ---**"); } @Test void testMethod1() { System.out.println("**--- Test method1 executed ---**"); } @DisplayName("Test method2 with condition") @Test void testMethod2() { System.out.println("**--- Test method2 executed ---**"); } @Test @Disabled("implementation pending") void testMethod3() { System.out.println("**--- Test method3 executed ---**"); } @AfterEach void afterEach() { System.out.println("**--- Executed after each test method in this class ---**"); } @AfterAll static void afterAll() { System.out.println("**--- Executed once after all test methods in this class ---**"); } }
We can run above JUnit test class in Eclipse -> Run As -> JUnit Test.
我们可以在Eclipse-> Run As-> JUnit Test中的 JUnit测试类之上运行 。
JUnit断言 (JUnit Assertions)
Every test method must be evaluated against condition to true using assertions so that the test can continue to execute. JUnit Jupiter assertions are kept in the org.junit.jupiter.api.Assertions class. All of the methods are static.
必须使用断言将每个测试方法的条件评估为true,以便测试可以继续执行。 JUnit Jupiter断言保存在org.junit.jupiter.api.Assertions类中。 所有方法都是静态的。
Assertion Description assertEquals(expected, actual) Fails when expected does not equal actual assertFalse(expression) Fails when expression is not false assertNull(actual) Fails when actual is not null assertNotNull(actual) Fails when actual is null assertAll() Group many assertions and every assertion is executed even if one or more of them fails assertTrue(expression) Fails if expression is not true assertThrows() Class to be tested is expected to throw an exception 断言 描述 assertEquals(预期的,实际的) 预期不等于实际时失败 assertFalse(表达式) 表达式不为假时失败 assertNull(实际) 实际不为空时失败 assertNotNull(实际) 当real为null时失败 assertAll() 对许多断言进行分组,并且每个断言都会执行,即使其中一个或多个失败 assertTrue(表达式) 如果表达式不正确则失败 assertThrows() 预期要测试的类将引发异常 @Test void testAssertEqual() { assertEquals("ABC", "ABC"); assertEquals(20, 20, "optional assertion message"); assertEquals(2 + 2, 4); } @Test void testAssertFalse() { assertFalse("FirstName".length() == 10); assertFalse(10 > 20, "assertion message"); } @Test void testAssertNull() { String str1 = null; String str2 = "abc"; assertNull(str1); assertNotNull(str2); } @Test void testAssertAll() { String str1 = "abc"; String str2 = "pqr"; String str3 = "xyz"; assertAll("numbers", () -> assertEquals(str1,"abc"), () -> assertEquals(str2,"pqr"), () -> assertEquals(str3,"xyz") ); //uncomment below code and understand each assert execution /*assertAll("numbers", () -> assertEquals(str1,"abc"), () -> assertEquals(str2,"pqr1"), () -> assertEquals(str3,"xyz1") );*/ } @Test void testAssertTrue() { assertTrue("FirstName".startsWith("F")); assertTrue(10 { throw new IllegalArgumentException("Illegal Argument Exception occured"); }); assertEquals("Illegal Argument Exception occured", exception.getMessage()); }
JUnit5导入 (JUnit5 Imports)
Its test classes need
org.junit.jupiter.api.Test
import statement and notorg.junit.Test
. Also, the test methods need not be a public and local package.它的测试类需要
org.junit.jupiter.api.Test
导入语句,而不是org.junit.Test
。 同样,测试方法不必是公共和本地程序包。import org.junit.jupiter.api.Test;
JUnit5假设 (JUnit5 Assumptions)
Assumptions are static methods in the
org.junit.jupiter.api.Assumptions
class. They will execute a test only when the specified condition met otherwise test will be aborted. The aborted test will not cause build failure. When an assumption fails,org.opentest4j.TestAbortedException
is thrown and the test is skipped.假设是
org.junit.jupiter.api.Assumptions
类中的静态方法。 他们仅在满足指定条件时执行测试,否则测试将中止。 中止的测试不会导致构建失败。 当假设失败时,将抛出org.opentest4j.TestAbortedException
并跳过测试。Assumptions Description assumeTrue Execute the body of lamda when the positive condition hold else test will be skipped assumeFalse Execute the body of lamda when the negative condition hold else test will be skipped assumingThat Portion of the test method will execute if an assumption holds true and everything after the lambda will execute irrespective of the assumption in assumingThat() holds 假设条件 描述 假设是真的 当阳性条件成立时执行lamda主体,否则将跳过测试 假设为假 负条件成立时执行lamda主体,否则将跳过测试 假如说 如果假设成立,则测试方法的一部分将执行,并且lambda之后的所有内容都将执行,而与前提条件thatthat()成立的情况无关 @Test void testAssumeTrue() { boolean b = 'A' == 'A'; assumeTrue(b); assertEquals("Hello", "Hello"); } @Test @DisplayName("test executes only on Saturday") public void testAssumeTrueSaturday() { LocalDateTime dt = LocalDateTime.now(); assumeTrue(dt.getDayOfWeek().getValue() == 6); System.out.println("further code will execute only if above assumption holds true"); } @Test void testAssumeFalse() { boolean b = 'A' != 'A'; assumeFalse(b); assertEquals("Hello", "Hello"); } @Test void testAssumeFalseEnvProp() { System.setProperty("env", "prod"); assumeFalse("dev".equals(System.getProperty("env"))); System.out.println("further code will execute only if above assumption hold"); } @Test void testAssumingThat() { System.setProperty("env", "test"); assumingThat("test".equals(System.getProperty("env")), () -> { assertEquals(10, 10); System.out.println("perform below assertions only on the test env"); }); assertEquals(20, 20); System.out.println("perform below assertions on all env"); }
JUnit嵌套测试类 (JUnit Nested Test Classes)
Nested tests allow to create nested classes and execute all of its test methods. The inner classes must be non-static. Just annotate inner classes with @Nested and all test methods inside it will be executed.
嵌套测试允许创建嵌套类并执行其所有测试方法。 内部类必须是非静态的。 只需使用@Nested注释内部类,即可执行其中的所有测试方法。
@BeforeAll static void beforeAll() { System.out.println("**--- JUnit5Sample4Test :: beforeAll :: Executed once before all test methods ---**"); } @BeforeEach void beforeEach() { System.out.println("**--- JUnit5Sample4Test :: beforeEach :: Executed before each test method ---**"); } @AfterEach void afterEach() { System.out.println("**--- JUnit5Sample4Test :: afterEach :: Executed after each test method ---**"); } @AfterAll static void afterAll() { System.out.println("**--- JUnit5Sample4Test :: afterAll :: Executed after all test method ---**"); } @Nested class InnerClass { @BeforeEach void beforeEach() { System.out.println("**--- InnerClass :: beforeEach :: Executed before each test method ---**"); } @AfterEach void afterEach() { System.out.println("**--- InnerClass :: afterEach :: Executed after each test method ---**"); } @Test void testMethod1() { System.out.println("**--- InnerClass :: testMethod1 :: Executed test method1 ---**"); } @Nested class InnerMostClass { @BeforeEach void beforeEach() { System.out.println("**--- InnerMostClass :: beforeEach :: Executed before each test method ---**"); } @AfterEach void afterEach() { System.out.println("**--- InnerMostClass :: afterEach :: Executed after each test method ---**"); } @Test void testMethod2() { System.out.println("**--- InnerMostClass :: testMethod2 :: Executed test method2 ---**"); } } }
JUnit测试异常 (JUnit Test Exception)
There are situations in which methods are expected to throw an exception under a specific condition. assertThrows will fail the test if the given method does not throw the specified exception.
在某些情况下,期望方法在特定条件下引发异常。 如果给定方法未引发指定的异常,则assertThrows将使测试失败。
Throwable exception = assertThrows(IllegalArgumentException.class, () -> { throw new IllegalArgumentException("Illegal Argument Exception occured"); }); assertEquals("Illegal Argument Exception occured", exception.getMessage());
JUnit测试执行 (JUnit Test Execution)
The unit tests can be executed in many ways, two of the ways are as follows:
单元测试可以通过多种方式执行,其中两种方式如下:
- Use Eclipse IDE Oxygen.3a (4.7.3a) Release and open test file to be executed. Right-click on the file and choose option Runs As followed by JUnit Test 使用Eclipse IDE Oxygen.3a(4.7.3a)发行并打开要执行的测试文件。 右键单击文件,然后选择选项Runs As,然后选择JUnit Test
- Use mvn test command on Windows command prompt 在Windows命令提示符下使用mvn test命令
摘要 (Summary)
We’ve explored JUnit5 and its new features with some examples. We also looked how we can use JUnit annotations, assertions, assumptions, exceptions and write nested test classes.
我们通过一些示例探索了JUnit5及其新功能。 我们还研究了如何使用JUnit批注,断言,假设,异常并编写嵌套的测试类。
GitHub Repository. GitHub Repository下载完整的示例项目。junit5教程