原文:Mkyong
JUnit 5 + AssertJ 示例
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-assertj-examples/
在本文中,我们将向您展示如何用 AssertJ 编写测试断言。
P.S 使用 JUnit 5.5.2 和 AssertJ 3.14.0 测试
pom.xml
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.14.0</version>
<scope>test</scope>
</dependency>
1.JUnit 5 对 AssertJ 的断言
将 JUnit 5 断言转换为 AssetJ 很容易,请参见以下语法:
JUnit 5
assertEquals(expected, actual);
assertEquals(expected, actual, "assertion desc");
AssertJ
assertThat(actual).isEqualTo(expected);
assertThat(actual).as("assertion desc").isEqualTo(expected);
2.AssertJ
2.1 一些带有 AssertJ 的典型测试断言—String
、List
、Map
和Exception
。
AssertjTest.java
package com.mkyong.assertions.assertj;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.assertj.core.data.Index;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
public class AssertjTest {
// assert string
@Test
void test_string_ok() {
String name = "I am Mkyong!";
assertThat(name)
.as("if failed display this msg!")
.isEqualTo("I am Mkyong!")
.isEqualToIgnoringCase("I AM mkyong!")
.startsWith("I")
.endsWith("!")
.containsIgnoringCase("mkyong");
}
// assert list
@Test
void test_list_ok() {
List<String> list = Arrays.asList("Java", "Rust", "Clojure");
assertThat(list)
.hasSize(3)
.contains("Java", "Clojure")
.contains("Java", Index.atIndex(0))
.contains("Rust", Index.atIndex(1))
.contains("Clojure", Index.atIndex(2))
.doesNotContain("Node JS");
}
// assert map
@Test
void test_map_ok() {
Map<String, Object> map = new HashMap<>();
map.put("name", "mkyong");
assertThat(map)
.hasSize(1)
.extractingByKey("name", as(InstanceOfAssertFactories.STRING))
.isEqualToIgnoringCase("mkyong")
.startsWith("mkyong");
assertThat(map).extracting("name")
.isEqualTo("mkyong");
Map<String, Object> map2 = new HashMap<>();
map2.put("number", 999);
assertThat(map2)
.hasSize(1)
.extractingByKey("number", as(InstanceOfAssertFactories.INTEGER))
.isEqualTo(999);
}
// assert exception
@Test
void test_exception_ok() {
assertThatThrownBy(() -> divide(1, 0))
.isInstanceOf(ArithmeticException.class)
.hasMessageContaining("zero")
.hasMessage("/ by zero");
assertThatThrownBy(() -> {
List<String> list = Arrays.asList("one", "two");
list.get(2);
})
.isInstanceOf(IndexOutOfBoundsException.class)
.hasMessageContaining("Index 2 out of bounds");
}
int divide(int input, int divide) {
return input / divide;
}
}
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/assertions/assertj/*.java
参考
JUnit 5 假设示例
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-assumptions-examples/
本文向您展示了如何使用 JUnit 5 假设来执行条件测试。
使用的技术:
- Maven 3.6
- Java 8
- JUnit 5.5.2
1.假设
1.1 如果assumeTrue()
条件为真,则运行测试,否则中止测试。
1.2assumingThat()
更加灵活,它允许部分代码作为条件测试运行。
AssumptionsTest.java
package com.mkyong;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.junit.jupiter.api.Assumptions.assumingThat;
public class AssumptionsTest {
// Output: org.opentest4j.TestAbortedException: Assumption failed: assumption is not true
@DisplayName("Run this if `assumeTrue` condition is true, else aborting this test")
@Test
void testOnlyOnDevEnvElseAbort() {
assumeTrue("DEV".equals(System.getenv("APP_MODE")));
assertEquals(2, 1 + 1);
}
// Output: org.opentest4j.TestAbortedException: Assumption failed: Aborting test: not on developer environment
@DisplayName("Run this if `assumeTrue` condition is true, else aborting this test (Custom Message)")
@Test
void testOnlyOnDevEnvElseAbortWithCustomMsg() {
assumeTrue("DEV".equals(System.getenv("APP_MODE")), () -> "Aborting test: not on developer environment");
assertEquals(2, 1 + 1);
}
@Test
void testAssumingThat() {
// run these assertions always, just like normal test
assertEquals(2, 1 + 1);
assumingThat("DEV".equals(System.getenv("APP_MODE")),
() -> {
// run this only if assumingThat condition is true
assertEquals(2, 1 + 1);
});
// run these assertions always, just like normal test
assertEquals(2, 1 + 1);
}
}
输出
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/AssumptionsTest.java
参考
JUnit 5 条件测试示例
本文向您展示了如何使用 JUnit 5 来基于条件启用或禁用测试。
用 JUnit 5.5.2 测试的 PS
1.操作系统
1.1 通过@EnabledOnOs
和@DisabledOnOs
注释基于特定操作系统启用或禁用测试。
OperatingSystemTest.java
package com.mkyong.conditional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
public class OperatingSystemTest {
@Test
@EnabledOnOs({
OS.LINUX, OS.WINDOWS})
void onLinuxOrWindows() {
System.out.println("Run this on Linux or Windows!");
}
@Test
@EnabledOnOs({
OS.WINDOWS})
void onWindows() {
System.out.println("Run this on Windows!");
}
@Test
@DisabledOnOs(OS.WINDOWS)
void notOnWindows() {
System.out.println("Do not run this on Windows!");
}
@Test
@DisabledOnOs({
OS.WINDOWS, OS.AIX, OS.SOLARIS, OS.MAC})
void notOnWindowsOrAixOrSolarisOrMac() {
System.out.println("Do not run this on Windows, AIX, Solaris or MAC!");
}
}
输出–使用 Windows 操作系统进行测试。
2.Java 运行时环境
2.1 通过@EnabledOnJre
和@DisabledOnJre
注释基于特定的 Java 运行时环境(JRE)启用或禁用测试。
JreTest.java
package com.mkyong.conditional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.EnabledOnJre;
import org.junit.jupiter.api.condition.JRE;
public class JreTest {
@Test
@EnabledOnJre(JRE.JAVA_9)
void onJava9() {
System.out.println("Run this on Java 9");
}
@Test
@EnabledOnJre({
JRE.JAVA_12, JRE.JAVA_13})
void onJava12OrJava13() {
System.out.println("Run this on Java 12 or Java 13");
}
@Test
@DisabledOnJre(JRE.JAVA_9)
void notOnJava9() {
System.out.println("Do not run this on Java 9");
}
}
输出–用 Java 13 测试
3.系统属性
3.1 通过@EnabledIfSystemProperty
和@DisabledIfSystemProperty
注释,根据 JVM 系统属性中named
的值启用或禁用测试。
SystemPropertyTest.java
package com.mkyong.conditional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import java.util.Properties;
public class SystemPropertyTest {
@Test
@EnabledIfSystemProperty(named = "java.vm.name", matches = ".*OpenJDK.*")
void onOpenJDK() {
System.out.println("Run this on OpenJDK!");
}
@Test
@DisabledIfSystemProperty(named = "user.country", matches = "MY")
void notOnCountryMalaysia() {
System.out.println("Do not run this on country code MY");
}
@Test
void printSystemProperties() {
Properties properties = System.getProperties();
properties.forEach((k, v) -> System.out.println(k + ":" + v));
}
}
4.环境变量
4.1 通过@EnabledIfEnvironmentVariable
和@DisabledIfEnvironmentVariable
注释,根据环境属性中named
的值启用或禁用测试。
EnvVariableTest.java
package com.mkyong.conditional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import java.util.Map;
public class EnvVariableTest {
@Test
@EnabledIfEnvironmentVariable(named = "PROCESSOR_IDENTIFIER", matches = ".*Intel64 Family 6.*")
void onIntel64() {
System.out.println("Run this on Intel6 Family 6 only.");
}
@Test
@EnabledIfEnvironmentVariable(named = "NUMBER_OF_PROCESSORS", matches = "8")
void onProcessor8() {
System.out.println("Run this if it has 8 processors.");
}
@Test
@DisabledIfEnvironmentVariable(named = "CURRENT_ENV", matches = ".*development.*")
void notOnDeveloperPC() {
System.out.println("Do not run this if env variables 'CURRENT_ENV' matches .*development.* ");
}
@Test
void printEnvironmentProperties() {
Map<String, String> env = System.getenv();
env.forEach((k, v) -> System.out.println(k + ":" + v));
}
}
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/conditional/*.java
参考
JUnit 5 控制台启动器示例
本文向您展示了如何使用 JUnit 5 ConsoleLauncher
从命令行运行测试。
测试对象
- JUnit 5.5.2
- JUnit-平台-控制台-独立版 1.5.2
1.下载 JAR
要从命令行运行测试,我们可以手动从 Maven central repository 下载JUnit-platform-console-standalone . jar。
这个例子使用的是版本1.5.2
。
https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console-standalone/1.5.2/
2.习惯
通常,测试类位于以下类路径中:
build/classes/java/test
target/test-classes
2.1 从此类路径运行所有测试build/classes/java/test
Terminal
$ java -jar junit-platform-console-standalone-1.5.2.jar --classpath build/classes/java/test --scan-classpath
$ java -jar junit-platform-console-standalone-1.5.2.jar -cp build/classes/java/test --scan-classpath
2.2 使用类名运行指定的测试。
Terminal
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp 'build/classes/java/test'
-c com.mkyong.order.MethodOrderTest
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp 'build/classes/java/test'
--select-class com.mkyong.order.MethodOrderTest
2.3 运行包中的所有测试。
Terminal
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp 'build/classes/java/test'
--select-package com.mkyong.order
2.4 运行包中的所有测试,通过正则表达式模式过滤测试的类名。
Terminal
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp 'build/classes/java/test'
--select-package com.mkyong.order
--include-classname='.*Count.*'
2.5 输出样本。
Terminal
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp 'build/classes/java/test'
--select-package com.mkyong.order
--include-classname='.*'
Thanks for using JUnit! Support its development at https://junit.org/sponsoring
+-- JUnit Jupiter [OK]
| +-- MethodRandomTest [OK]
| | +-- testA() [OK]
| | +-- testZ() [OK]
| | +-- testY() [OK]
| | +-- testE() [OK]
| | '-- testB() [OK]
| +-- MethodParameterCountTest [OK]
| | +-- Parameter Count : 3 [OK]
| | | +-- 1 ==> fruit='apple', qty=1, price=1.99 [OK]
| | | '-- 2 ==> fruit='banana', qty=2, price=2.99 [OK]
| | +-- Parameter Count : 2 [OK]
| | | +-- 1 ==> fruit='apple', qty=1 [OK]
| | | '-- 2 ==> fruit='banana', qty=2 [OK]
| | '-- Parameter Count : 1 [OK]
| | +-- 1 ==> ints=1 [OK]
| | +-- 2 ==> ints=2 [OK]
| | '-- 3 ==> ints=3 [OK]
| +-- MethodAlphanumericTest [OK]
| | +-- testA() [OK]
| | +-- testB() [OK]
| | +-- testE() [OK]
| | +-- testY() [OK]
| | '-- testZ() [OK]
| '-- MethodOrderTest [OK]
| +-- test2() [OK]
| +-- test3() [OK]
| +-- test1() [OK]
| +-- test0() [OK]
| '-- test4() [OK]
'-- JUnit Vintage [OK]
Test run finished after 109 ms
[ 9 containers found ]
[ 0 containers skipped ]
[ 9 containers started ]
[ 0 containers aborted ]
[ 9 containers successful ]
[ 0 containers failed ]
[ 22 tests found ]
[ 0 tests skipped ]
[ 22 tests started ]
[ 0 tests aborted ]
[ 22 tests successful ]
[ 0 tests failed ]
附:请参考 JUnit 5 官方指南,了解所有控制台启动器选项
3.Windows 操作系统
3.1 如果我们想在经典命令提示符下运行上述命令,请用双引号替换单引号,例如:
Command Prompt – Windows
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp "build/classes/java/test"
-c com.mkyong.order.MethodOrderTest
3.2 传递一个--disable-ansi-colors
选项来禁用输出中的 ANSI 颜色。命令提示符不支持此功能。
Command Prompt – Windows
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp "build/classes/java/test"
-c com.mkyong.order.MethodOrderTest
--disable-ansi-colors
下载源代码
$ git clone https://github.com/mkyong/junit-examples
参考
JUnit 5 显示名称
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-display-names/
在 JUnit 5 中,我们可以使用@DisplayName
来声明测试类和测试方法的定制显示名称。
用 JUnit 5.5.2 测试的 PS
1.@DisplayName
1.1 测试类和方法的默认名称。
DisplayNameTest.java
package com.mkyong.display;
import org.junit.jupiter.api.Test;
public class DisplayNameTest {
@Test
void test_spaces_ok() {
}
@Test
void test_spaces_fail() {
}
}
输出
+-- JUnit Jupiter [OK]
| '-- DisplayNameTest [OK]
| +-- test_spaces_ok() [OK]
| '-- test_spaces_fail() [OK]
1.2 @DisplayName
DisplayNameCustomTest.java
package com.mkyong.display;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("I'm a Test Class")
public class DisplayNameCustomTest {
@Test
@DisplayName("Test with spaces, expected ok")
void test_spaces_ok() {
}
@DisplayName("Test with spaces, expected failed")
@Test
void test_spaces_fail() {
}
}
输出
+-- JUnit Jupiter [OK]
| '-- I'm a Test Class [OK]
| +-- Test with spaces, expected ok [OK]
| '-- Test with spaces, expected failed [OK]
2.显示名称生成器
2.1 我们还可以创建一个自定义显示名称生成器,并通过@DisplayNameGeneration
进行配置。
2.2 这个例子使用 JUnit ReplaceUnderscores
生成器将下划线替换为空格。
DisplayNameGenerator1Test.java
package com.mkyong.display;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
public class DisplayNameGenerator1Test {
@Test
void test_spaces_ok() {
}
@Test
void test_spaces_fail() {
}
}
输出
2.3 我们可以扩展 JUnit DisplayNameGenerator
来创建我们的自定义显示名称生成器。
DisplayNameGenerator2Test.java
package com.mkyong.display;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;
@DisplayNameGeneration(DisplayNameGenerator2Test.CustomDisplayNameGenerator.class)
public class DisplayNameGenerator2Test {
@Test
void test_spaces_ok() {
}
@Test
void test_spaces_fail() {
}
static class CustomDisplayNameGenerator extends DisplayNameGenerator.Standard {
@Override
public String generateDisplayNameForClass(Class<?> testClass) {
return "New Name for test class";
}
@Override
public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
return super.generateDisplayNameForNestedClass(nestedClass);
}
@Override
public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
String name = testMethod.getName();
return Arrays.stream(name.split("_")).collect(Collectors.joining(" | "));
}
}
}
输出
3.参数化测试
3.1 对于参数化测试,我们可以通过@ParameterizedTest
的 name 属性来声明自定义显示名称,参见下面的例子:
DisplayNameParamTest.java
package com.mkyong.display;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import static org.junit.jupiter.params.provider.Arguments.arguments;
public class DisplayNameParamTest {
@ParameterizedTest(name = "#{index} - Test with TimeUnit: {0}")
@EnumSource(value = TimeUnit.class, names = {
"MINUTES", "SECONDS"})
void test_timeunit_ok(TimeUnit time) {
}
@ParameterizedTest(name = "#{index} - Test with {0} and {1}")
@MethodSource("argumentProvider")
void test_method_multi(String str, int length) {
}
static Stream<Arguments> argumentProvider() {
return Stream.of(
arguments("abc", 3),
arguments("lemon", 2)
);
}
}
输出
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/display/*.java
参考
JUnit 5 预期异常
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-expected-exception/
在 JUnit 5 中,我们可以使用assertThrows
来断言抛出了异常。
用 JUnit 5.5.2 测试的 PS
1.未检查的异常
1.1 捕捉运行时异常的 JUnit 示例。
ExceptionExample1.java
package com.mkyong.assertions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ExceptionExample1 {
@Test
void test_exception() {
Exception exception = assertThrows(
ArithmeticException.class,
() -> divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
assertTrue(exception.getMessage().contains("zero"));
}
int divide(int input, int divide) {
return input / divide;
}
}
2.检查异常
2.1 捕捉自定义/编译时异常的 JUnit 示例。
NameNotFoundException.java
package com.mkyong.assertions;
public class NameNotFoundException extends Exception {
public NameNotFoundException(String message) {
super(message);
}
}
ExceptionExample2.java
package com.mkyong.assertions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ExceptionExample2 {
@Test
void test_exception_custom() {
Exception exception = assertThrows(
NameNotFoundException.class,
() -> findByName("mkyong"));
assertTrue(exception.getMessage().contains("not found"));
}
String findByName(String name) throws NameNotFoundException{
throw new NameNotFoundException( name + " not found!");
}
}
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/assertions/*.java
参考
JUnit 5 + Gradle 示例
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/gradle/junit-5-gradle-examples/
本文向您展示了如何在 Gradle 项目中添加 JUnit 5。
使用的技术:
- Gradle 5.4.1
- Java 8
- JUnit 5.5.2
1.Gradle + JUnit 5
1.添加 JUni 5 jupiter 引擎,并如下定义useJUnitPlatform()
:
gradle.build
plugins {
id 'java'
id 'eclipse' // optional, for Eclipse project
id 'idea' // optional, for IntelliJ IDEA project
}
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.5.2')
}
test {
useJUnitPlatform()
}
2.Gradle 项目
标准的 Java 项目结构。
3.JUnit 5
3.1 一个简单的单元测试例子。
MessageService.java
package com.mkyong.core;
public class MessageService {
public static String get() {
return "Hello JUnit 5";
}
}
3.2 JUnit 5 简单Assertions
测试。
MessageServiceTest.java
package com.mkyong.core;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MessageServiceTest {
@DisplayName("Test MessageService.get()")
@Test
void testGet() {
assertEquals("Hello JUnit 5", MessageService.get());
}
}
4 .测试等级
4.1 在 Gradle 中运行测试。
Terminal
$ cd project
$ gradle test
BUILD SUCCESSFUL in 0s
3 actionable tasks: 3 up-to-date
4.2 如果测试失败,它将显示如下内容:
Terminal
$ gradle test
> Task :test FAILED
com.mkyong.core.MessageServiceTest > testGet() FAILED
org.opentest4j.AssertionFailedError at MessageServiceTest.java:13
1 test completed, 1 failed
4.3 gradle test
默认生成如下 HTML 测试报告:
{project}\build\reports\tests\test\index.html
完成了。
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-gradle
$ gradle test
参考
- JUnit 5 官方网站
- Spring Boot +朱尼特 5 +莫奇托
- Java 测试& JVM 项目
JUnit 5–如何禁用测试?
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-how-to-disable-tests/
JUnit 5 @Disabled
示例禁用对整个测试类或单个测试方法的测试。
用 JUnit 5.5.2 测试的 PS
Note
You can also disable tests based on conditions.
1.@在方法上禁用
1.1 测试方法testCustomerServiceGet
被禁用。
DisabledMethodTest.java
package com.mkyong.disable;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class DisabledMethodTest {
@Disabled("Disabled until CustomerService is up!")
@Test
void testCustomerServiceGet() {
assertEquals(2, 1 + 1);
}
@Test
void test3Plus3() {
assertEquals(6, 3 + 3);
}
}
输出–使用 Intellij IDE 运行。
2.@在课堂上被禁用
2.1 整个测试类将被禁用。
DisabledClassTest.java
package com.mkyong.disable;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
@Disabled("Disabled until bug #2019 has been fixed!")
public class DisabledClassTest {
@Test
void test1Plus1() {
assertEquals(2, 1 + 1);
}
@Test
void test2Plus2() {
assertEquals(4, 2 + 2);
}
}
经过测试,它在 Maven 或 Gradle 构建工具中运行正常。
Note
However, run the above test under Intellij IDE, the @Disabled
on class level is NOT working as expected, no idea why?
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/disable/*.java
参考
JUnit 5 + Maven 示例
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-maven-examples/
这篇文章向你展示了如何在一个 Maven 项目中添加 JUnit 5,没什么特别的,只是添加 JUnit 5 junit-jupiter-engine
库并确保maven-surefire-plugin
至少是版本2.22.0
使用的技术:
- Maven 3.6
- Java 8
- JUnit 5.5.2
1.腹部+6 月 5 日
1.添加 JUni 5 jupiter 引擎。
pom.xml
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
2.要在 Maven 中运行测试,maven-surefire-plugin
必须至少是版本2.22.0
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong.core</groupId>
<artifactId>junit5-maven</artifactId>
<version>1.0</version>
<properties>
<java.version>1.8</java.version>
<junit-jupiter.version>5.5.2</junit-jupiter.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- junit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${
junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Need at least 2.22.0 to support JUnit 5 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.Maven 项目
一个简单的 Maven 项目结构。
3.JUnit 5
3.1 一个简单的单元测试例子。
MessageService.java
package com.mkyong.core;
public class MessageService {
public static String get() {
return "Hello JUnit 5";
}
}
3.2 JUnit 5 简单Assertions
测试。
MessageServiceTest.java
package com.mkyong.core;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MessageServiceTest {
@DisplayName("Test MessageService.get()")
@Test
void testGet() {
assertEquals("Hello JUnit 5", MessageService.get());
}
}
3.3 在 IntelliJ IDEA 中运行,输出:
4.mvn 试验
4.1Maven Surefire Plugin
将扫描并运行以下测试类:
**/Test*.java
**/*Test.java
**/*Tests.java
**/*TestCase.java
Terminal
$ cd project
$ mvn test
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mkyong.core.MessageServiceTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0,
Time elapsed: 0.02 s - in com.mkyong.core.MessageServiceTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.488 s
[INFO] Finished at: 2019-09-14T10:27:01+08:00
[INFO] ------------------------------------------------------------------------
测试结果将在project\target\surefire-reports
以.txt
和.xml
两种格式生成。
5.mvn 站点
5.1 最好生成一个项目站点,以 HTML 格式查看单元测试结果。要将 surefire 单元测试报告添加到站点中,请添加以下reporting
部分。
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.8.2</version>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
</plugin>
</plugins>
</reporting>
Terminal
$ cd project
$ mvn site
项目网站将在project\target\site
生成,点击index.html
点击project reports
->-surefire report
完成了。
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-maven
$ mvn test
参考
JUnit 5 嵌套测试
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-nested-test-examples/
本文向您展示了如何使用 JUnit 5 @Nested
注释将测试分组在一起。
用 JUnit 5.5.2 测试的 PS
为什么是嵌套测试?
创建嵌套测试是可选的。尽管如此,创建层次化的上下文来将相关的单元测试组织在一起还是有帮助的;简而言之,它有助于保持测试的整洁和可读性。
让我们看看下面的例子——对一个CustomerService
的测试。
1.单一测试类别
1.1 默认情况下,我们可以在一个类中创建所有的测试,如下所示:
CustomerServiceMethodTest.java
package com.mkyong.nested.samples;
import com.mkyong.customer.service.CustomerService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("Test Customer Service")
public class CustomerServiceMethodTest {
CustomerService customerService;
@BeforeEach
void createNewObjectForAll() {
System.out.println("New CustomerService()");
//customerService = new CustomerServiceJDBC();
}
@Test
void findOne_with_id() {
//customerService.findOneById(2L);
}
@Test
void findOne_with_name() {
//customerService.findOneByName(2L);
}
@Test
void findOne_with_name_regex() {
//customerService.findOneByNameRegex("%s");
}
@Test
void findAll_with_ids() {
//customerService.findAllByIds(Arrays.asList(2, 3, 4));
}
@Test
void findAll_with_name_like() {
//customerService.findAllByName("mkyong");
}
@Test
void update_with_new() {
//customerService.update(new Customer());
}
@Test
void update_with_existing() {
//customerService.update(new Customer());
}
}
IDE 中的输出。
如果CustomerService
增加了更多的特性,那么这个测试类将很容易被数百个测试方法所超载。最后,我们创建了一个混乱的、有意义的、无组织的单一测试类。
2.分类测试
2.1 一些开发人员开始按照类名对相关测试进行分组,如下所示:
CustomerServiceFindOneTest.java
package com.mkyong.nested.samples;
import com.mkyong.customer.service.CustomerService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class CustomerServiceFindOneTest {
CustomerService customerService;
@BeforeEach
void createNewObjectForAll() {
System.out.println("New CustomerService()");
//customerService = new CustomerServiceJDBC();
}
@Test
void findOne_with_id() {
//customerService.findOneById(2L);
}
@Test
void findOne_with_name() {
//customerService.findOneByName(2L);
}
@Test
void findOne_with_name_regex() {
//customerService.findOneByNameRegex("%s");
}
}
CustomerServiceFindAllTest.java
package com.mkyong.nested.samples;
import com.mkyong.customer.service.CustomerService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class CustomerServiceFindAllTest {
CustomerService customerService;
@BeforeEach
void createNewObjectForAll() {
System.out.println("New CustomerService()");
//customerService = new CustomerServiceJDBC();
}
@Test
void findAll_with_ids() {
//customerService.findAllByIds(Arrays.asList(2, 3, 4));
}
@Test
void findAll_with_name_likeY() {
//customerService.findAllByName("mkyong");
}
}
CustomerServiceUpdateTest.java
package com.mkyong.nested.samples;
import com.mkyong.customer.service.CustomerService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class CustomerServiceUpdateTest {
CustomerService customerService;
@BeforeEach
void createNewObjectForAll() {
System.out.println("New CustomerService()");
//customerService = new CustomerServiceJDBC();
}
@Test
void update_with_new() {
//customerService.update(new Customer());
}
@Test
void update_with_existing() {
//customerService.update(new Customer());
}
}
如果CustomerService
增加了更多的特性,例如,新的 30 多个方法,我们会为CustomerService
创建 30 多个测试类吗?如何运行 30 多个测试类,通过模式还是创建一个新的测试套件?
3.嵌套测试
3.1 对于大类,我们应该考虑@Nested
测试,单个测试类中的所有测试(在一个层次结构中),IDE 中的层次输出使测试更具可读性。
此外,我们还可以初始化一个对象,并对所有嵌套的测试进行重用。
CustomerServiceNestedTest.java
package com.mkyong.nested;
import com.mkyong.customer.service.CustomerService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@DisplayName("Test Customer Service")
public class CustomerServiceNestedTest {
CustomerService customerService;
// Create one customerService object and reuse for all the nested tests
@Test
@DisplayName("new CustomerService() for all the nested methods.")
void createNewObjectForAll() {
System.out.println("New CustomerService()");
//customerService = new CustomerServiceJDBC();
}
@Nested
@DisplayName("findOne methods")
class FindOne {
@Test
void findOne_with_id() {
//customerService.findOneById(2L);
}
@Test
void findWith_with_name() {
//customerService.findOneByName(2L);
}
@Test
void findWith_with_name_regex() {
//customerService.findOneByNameRegex("%s");
}
}
@Nested
@DisplayName("findAll methods")
class FindAll {
@Test
void findAll_with_ids() {
//customerService.findAllByIds(Arrays.asList(2, 3, 4));
}
@Test
void findAll_with_name_likeY() {
//customerService.findAllByName("mkyong");
}
}
@Nested
@DisplayName("update methods")
class Update {
@Test
void update_with_new() {
//customerService.update(new Customer());
}
@Test
void update_with_existing() {
//customerService.update(new Customer());
}
}
}
IDE 中的输出。
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/nested/*.java
参考
JUnit 5 参数化测试
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-parameterized-tests/
本文向您展示了如何使用不同的参数多次运行一个测试,即所谓的“参数化测试”,让我们来看看以下为测试提供参数的方法:
@ValueSource
@EnumSource
@MethodSource
@CsvSource
@CsvFileSource
@ArgumentsSource
我们需要junit-jupiter-params
来支持参数化测试。
pom.xml
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<!-- Parameterized Tests -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
用 JUnit 5.5.2 测试的 PS
1.@ValueSource
1.1 为单参数测试。
ValueSourceTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ValueSourceTest {
// This test will run 3 times with different arguments
@ParameterizedTest
@ValueSource(ints = {
1, 2, 3})
void test_int_arrays(int arg) {
assertTrue(arg > 0);
}
@ParameterizedTest(name = "#{index} - Run test with args={0}")
@ValueSource(ints = {
1, 2, 3})
void test_int_arrays_custom_name(int arg) {
assertTrue(arg > 0);
}
@ParameterizedTest(name = "#{index} - Run test with args={0}")
@ValueSource(strings = {
"apple", "banana", "orange"})
void test_string_arrays_custom_name(String arg) {
assertTrue(arg.length() > 1);
}
}
输出
1.2 我们可以通过@EmptySource
、@NullSource
或@NullAndEmptySource
将空值或 null 值传递到测试中(从 JUnit 5.4 开始)。让我们看下面的例子来测试一个isEmpty()
方法。
ValueSourceEmptyTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ValueSourceEmptyTest {
boolean isEmpty(String input) {
return (input == null || input.length() == 0);
}
// run 3 times, 1 for empty, 1 for null, 1 for ""
@ParameterizedTest(name = "#{index} - isEmpty()? {0}")
@EmptySource
@NullSource
//@NullAndEmptySource
@ValueSource(strings = {
""})
void test_is_empty_true(String arg) {
assertTrue(isEmpty(arg));
}
@ParameterizedTest(name = "#{index} - isEmpty()? {0}")
@ValueSource(strings = {
" ", "\n", "a", "\t"})
void test_is_empty_false(String arg) {
assertFalse(isEmpty(arg));
}
}
输出
2.@EnumSource
2.1 运行以Enum
为参数的测试。
EnumSourceTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import java.util.EnumSet;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
public class EnumSourceTest {
enum Size {
XXS, XS, S, M, L, XL, XXL, XXXL;
}
@ParameterizedTest
@EnumSource(Size.class)
void test_enum(Size size) {
assertNotNull(size);
}
@ParameterizedTest(name = "#{index} - Is size contains {0}?")
@EnumSource(value = Size.class, names = {
"L", "XL", "XXL", "XXXL"})
void test_enum_include(Size size) {
assertTrue(EnumSet.allOf(Size.class).contains(size));
}
// Size = M, L, XL, XXL, XXXL
@ParameterizedTest
@EnumSource(value = Size.class, mode = EXCLUDE, names = {
"XXS", "XS", "S"})
void test_enum_exclude(Size size) {
EnumSet<Size> excludeSmallSize = EnumSet.range(Size.M, Size.XXXL);
assertTrue(excludeSmallSize.contains(size));
}
}
输出。
$ java -jar junit-platform-console-standalone-1.5.2.jar
-cp "target/test-classes/"
--select-class com.mkyong.params.EnumSourceTest
--disable-ansi-colors
+-- JUnit Jupiter [OK]
| '-- EnumSourceTest [OK]
| +-- test_enum_include(Size) [OK]
| | +-- #1 - Is size contains L? [OK]
| | +-- #2 - Is size contains XL? [OK]
| | +-- #3 - Is size contains XXL? [OK]
| | '-- #4 - Is size contains XXXL? [OK]
| +-- test_enum(Size) [OK]
| | +-- [1] XXS [OK]
| | +-- [2] XS [OK]
| | +-- [3] S [OK]
| | +-- [4] M [OK]
| | +-- [5] L [OK]
| | +-- [6] XL [OK]
| | +-- [7] XXL [OK]
| | '-- [8] XXXL [OK]
| '-- test_enum_exclude(Size) [OK]
| +-- [1] M [OK]
| +-- [2] L [OK]
| +-- [3] XL [OK]
| +-- [4] XXL [OK]
| '-- [5] XXXL [OK]
'-- JUnit Vintage [OK]
3.@MethodSource
3.1 运行使用静态method
生成参数的测试。
MethodSourceTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class MethodSourceTest {
@ParameterizedTest(name = "#{index} - Test with String : {0}")
@MethodSource("stringProvider")
void test_method_string(String arg) {
assertNotNull(arg);
}
// this need static
static Stream<String> stringProvider() {
return Stream.of("java", "rust");
}
@ParameterizedTest(name = "#{index} - Test with Int : {0}")
@MethodSource("rangeProvider")
void test_method_int(int arg) {
assertTrue(arg < 10);
}
// this need static
static IntStream rangeProvider() {
return IntStream.range(0, 10);
}
}
输出
+-- JUnit Jupiter [OK]
| '-- MethodSourceTest [OK]
| +-- test_method_int(int) [OK]
| | +-- #1 - Test with Int : 0 [OK]
| | +-- #2 - Test with Int : 1 [OK]
| | +-- #3 - Test with Int : 2 [OK]
| | +-- #4 - Test with Int : 3 [OK]
| | +-- #5 - Test with Int : 4 [OK]
| | +-- #6 - Test with Int : 5 [OK]
| | +-- #7 - Test with Int : 6 [OK]
| | +-- #8 - Test with Int : 7 [OK]
| | +-- #9 - Test with Int : 8 [OK]
| | '-- #10 - Test with Int : 9 [OK]
| '-- test_method_string(String) [OK]
| +-- #1 - Test with String : java [OK]
| '-- #2 - Test with String : rust [OK]
'-- JUnit Vintage [OK]
3.2 多重论证
MethodSourceMultiTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.Arguments.arguments;
public class MethodSourceMultiTest {
@ParameterizedTest
@MethodSource("stringIntAndListProvider")
void testWithMultiArgMethodSource(String str, int length, List<String> list) {
assertTrue(str.length() > 0);
assertEquals(length, list.size());
}
static Stream<Arguments> stringIntAndListProvider() {
return Stream.of(
arguments("abc", 3, Arrays.asList("a", "b", "c")),
arguments("lemon", 2, Arrays.asList("x", "y"))
);
}
}
输出
+-- JUnit Jupiter [OK]
| '-- MethodSourceMultiTest [OK]
| '-- test_method_multi(String, int, List) [OK]
| +-- [1] abc, 3, [a, b, c] [OK]
| '-- [2] lemon, 2, [x, y] [OK]
'-- JUnit Vintage [OK]
4.@CsvSource
4.1 运行以逗号分隔值(csv)作为参数的测试。
CsvSourceTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CsvSourceTest {
@ParameterizedTest
@CsvSource({
"java, 4",
"clojure, 7",
"python, 6"
})
void test_csv(String str, int length) {
assertEquals(length, str.length());
}
}
5.@CsvFileSource
5.1 从文件中导入逗号分隔值(csv)作为参数。
src/test/resources/simple.csv
java, 4
clojure, 7
python, 6
CsvFileSourceTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CsvFileSourceTest {
// Skip the first line
@ParameterizedTest
@CsvFileSource(resources = "/simple.csv", numLinesToSkip = 1)
void test_csv_file(String str, int length) {
assertEquals(length, str.length());
}
}
输出
+-- JUnit Jupiter [OK]
| '-- CsvFileSourceTest [OK]
| '-- test_csv_file(String, int) [OK]
| +-- [1] clojure, 7 [OK]
| '-- [2] python, 6 [OK]
'-- JUnit Vintage [OK]
6.@ArgumentsSource
6.1 创建可重用的参数提供程序。
CustomArgumentsProvider.java
package com.mkyong.params;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.stream.Stream;
public class CustomArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments>
provideArguments(ExtensionContext extensionContext) throws Exception {
return Stream.of("java", "rust", "kotlin").map(Arguments::of);
}
}
ArgumentsSourceTest.java
package com.mkyong.params;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class ArgumentsSourceTest {
@ParameterizedTest
@ArgumentsSource(CustomArgumentsProvider.class)
void test_argument_custom(String arg) {
assertNotNull(arg);
}
}
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/params/*.java
参考
JUnit 5 重复测试
原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-repeated-tests/
本文向您展示了如何使用 JUnit 5 @RepeatedTest
来重复测试指定的次数。
用 JUnit 5.5.2 测试的 PS
1.@重复测试
1.1@RepeatedTest
测试方法就像常规的@Test
方法一样,相同的生命周期。
RepeatedSample1Test.java
package com.mkyong.repeated;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class RepeatedSample1Test {
@BeforeAll
static void beforeAll() {
System.out.println("beforeAll");
}
@AfterAll
static void afterAll() {
System.out.println("afterAll");
}
@BeforeEach
void beforeEach() {
System.out.println("beforeEach");
}
@AfterEach
void afterEach() {
System.out.println("afterEach");
}
// Repeat this test 3 times
@RepeatedTest(3)
void math_add_1() {
System.out.println("Run math_add_1()");
assertEquals(2, 1 + 1);
}
@RepeatedTest(3)
void math_add_2() {
System.out.println("Run math_add_2()");
assertEquals(2, 1 + 1);
}
}
IDE 中的输出。
控制台中的输出。
beforeAll
beforeEach
Run math_add_1()
afterEach
beforeEach
Run math_add_1()
afterEach
beforeEach
Run math_add_1()
afterEach
beforeEach
Run math_add_2()
afterEach
beforeEach
Run math_add_2()
afterEach
beforeEach
Run math_add_2()
afterEach
afterAll
2.自定义测试名称
2.1 我们可以配置@RepeatedTest
方法的名称。
RepeatedSample2Test.java
package com.mkyong.repeated;
import org.junit.jupiter.api.RepeatedTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class RepeatedSample2Test {
@RepeatedTest(3)
void math_add_1() {
System.out.println("Run math_add_1()");
assertEquals(2, 1 + 1);
}
@RepeatedTest(value = 3, name = RepeatedTest.LONG_DISPLAY_NAME)
void math_add_2() {
System.out.println("Run math_add_2()");
assertEquals(2, 1 + 1);
}
@RepeatedTest(value = 3, name = "{displayName} - ABC - {currentRepetition}/{totalRepetitions}")
void math_add_3() {
System.out.println("Run math_add_3()");
assertEquals(2, 1 + 1);
}
}
IDE 中的输出。
注意
{displayName}
:测试方法的名称。{currentRepetition}
:当前重复次数。{totalRepetitions}
:总重复次数。
3.重复信息
3.1 我们也可以将RepetitionInfo
作为参数注入,并访问@RepeatedTest
的元数据。
@RepeatedTest.java
package com.mkyong.repeated;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class RepeatedSample3Test {
@RepeatedTest(3)
void math_add_4(RepetitionInfo repetitionInfo) {
System.out.println("Repetition #" + repetitionInfo.getCurrentRepetition());
assertEquals(3, repetitionInfo.getTotalRepetitions());
}
}
控制台中的输出。
Repetition #1
Repetition #2
Repetition #3
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/repeated/*.java
参考
JUnit 5 标签和过滤,@标签示例
本文向您展示了如何通过@Tag
注释使用 JUnit 5 标记和过滤。
测试对象
- JUnit 5.5.2
- Maven 3.6.0
- Gradle 5.6.2
1.@标签
一个简单的标签演示。
TagMethodTest.java
package com.mkyong.tags;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Tag("branch-20")
public class TagMethodTest {
@Test
@Tag("feature-168")
void test1Plus1() {
assertEquals(2, 1 + 1);
}
@Test
@Tag("integration")
@Tag("fast")
void testFastAndIntegration() {
assertEquals(2, 1 + 1);
}
@Test
@Tag("slow")
void testSlow() {
assertEquals(2, 1 + 1);
}
}
2.Maven 过滤测试
2.1 在 Maven 中,我们可以通过maven-surefire-plugin
的配置参数运行基于标签的测试
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<!-- include tags -->
<groups>integration, feature-168</groups>
<!-- exclude tags -->
<excludedGroups>slow</excludedGroups>
</configuration>
</plugin>
2.2 在控制台中,使用-D
选项。
Terminal
# Run tests which tagged with `integration, slow, feature-168`
$ mvn -Dgroups="integration, fast, feature-168"
# Exclude tests which tagged with 'slow'
$ mvn -DexcludedGroups="slow"
3.梯度过滤试验
3.1 在 Gradle 中,我们可以像这样过滤标签:
build.gradle
test {
useJUnitPlatform{
includeTags 'integration', 'feature-168'
excludeTags 'slow'
}
}
运行标记有integration' and
feature-168`的测试
Terminal
$ gradle clean test
> Task :test
com.mkyong.tags.TagMethodTest > testFastAndIntegration() PASSED
com.mkyong.tags.TagMethodTest > test1Plus1() PASSED
3.2 不知道如何在控制台中传递includeTags
参数,而是创建一个新的测试任务。
build.gradle
task slowTest(type: Test) {
useJUnitPlatform {
includeTags 'slow'
}
}
运行标记为“慢”的测试
Terminal
$ gradle clean slowtest
> Task :slowTest
com.mkyong.tags.TagMethodTest > testSlow() PASSED
Note
JUnit 5 supports Tag Expressions.
下载源代码
$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$ check src/test/java/com/mkyong/tag/*.java
$ check pom.xml, uncomment tags stuff
$ mvn test
$ check build.gradle, uncomment tags stuff
$ gradle test