Mkyong 中文博客翻译(四十一)

原文:Mkyong

协议:CC BY-NC-SA 4.0

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 的典型测试断言—StringListMapException

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 条件测试示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-conditional-test-examples/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文向您展示了如何使用 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));
    }

} 

阅读此–如何用 Java 打印所有系统属性

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 控制台启动器示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-consolelauncher-examples/

本文向您展示了如何使用 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–如何禁用测试?

原文: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 标签和过滤,@标签示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/junit5/junit-5-tagging-and-filtering-tag-examples/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文向您展示了如何通过@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

参考

猜你喜欢

转载自blog.csdn.net/wizardforcel/article/details/143497869