When we write standard test cases using @Test annotation then tests are static in nature so that is fully specified at compile time and their behavior cannot be changed by anything happening at runtime.
A dynamic test is a test that is generated at runtime by a factory method that is annotated with @TestFactory.
A @TestFactory method is not itself a test case but rather a factory for test cases
A @TestFactory method must return a single DynamicNode or a Stream, Collection, Iterable, Iterator, or array of DynamicNode instances.
@TestFactory methods must not be private or static
Let’s try to understand the above concept using a demo project
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kkjavatutorials</groupId> <artifactId>JUnit5DynamicTestExamples</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.target>8</maven.compiler.target> <maven.compiler.source>8</maven.compiler.source> <junit.jupiter.version>5.6.2</junit.jupiter.version> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.jupiter.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.jupiter.version}</version> <scope>test</scope> </dependency> </dependencies> </project> |
MyUtils.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package com.kkjavatutorials; public class MyUtils { /** * Method perform addition of two numbers * @param n1 first input number * @param n2 second input number * @return addition of two numbers */ public int add(int n1, int n2) { return n1+n2; } /** * Method to check whether input String is Palindrome or not * @param inputText * @return return true if input is Palindrome else false */ public static boolean isPalindrome(String inputText) { return new StringBuffer(inputText).reverse().toString().equals(inputText); } /** * Method perform multiplication of two numbers * @param n1 first input number * @param n2 second input number * @return multiplication of two numbers */ public static Integer multiply(int n1, int n2) { return n1*n2; } } |
DynamicTestsDemo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
package com.kkjavatutorials; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; /** * Dynamic Tests JUnit Examples * @author KK JavaTutorials */ class DynamicTestsDemo { /** * This will result in a JUnitException at Runtime because * TestFactory has invalid return type * @return */ @TestFactory List<String> dynamicTestsWithInvalidReturnType() { return Arrays.asList("KK JavaTurials"); } /** * Dynamic Tests to check Stream of strings are Palindrome or not * @return */ @TestFactory Stream<DynamicTest> dynamicTestsForPalindromes(){ return Stream.of("pop","radar","mom","dad","madam").map(inputText->dynamicTest(inputText, ()->assertTrue(MyUtils.isPalindrome(inputText)))); } /** * Dynamic Tests for Collection * @return */ @TestFactory Collection<DynamicTest> dynamicTestsFromCollection() { return Arrays.asList( dynamicTest("1st dynamic test", () -> assertTrue(MyUtils.isPalindrome("radar"))), dynamicTest("2nd dynamic test", () -> assertEquals(81, MyUtils.multiply(9, 9))) ); } /** * Dynamic Tests for Iterable * @return */ @TestFactory Iterable<DynamicTest> dynamicTestsFromIterable() { return Arrays.asList( dynamicTest("3rd dynamic test", () -> assertTrue(MyUtils.isPalindrome("dad"))), dynamicTest("4th dynamic test", () -> assertEquals(9, MyUtils.multiply(3, 3))) ); } /** * Dynamic Tests for Iterator * @return */ @TestFactory Iterator<DynamicTest> dynamicTestsFromIterator() { return Arrays.asList( dynamicTest("5th dynamic test", () -> assertTrue(MyUtils.isPalindrome("madam"))), dynamicTest("6th dynamic test", () -> assertEquals(25, MyUtils.multiply(5, 5))) ).iterator(); } /** * Dynamic Tests for Array * @return */ @TestFactory DynamicTest[] dynamicTestsFromArray() { return new DynamicTest[] { dynamicTest("7th dynamic test", () -> assertTrue(MyUtils.isPalindrome("dad"))), dynamicTest("8th dynamic test", () -> assertEquals(16, MyUtils.multiply(4, 4))) }; } /** * Dynamic Tests for Stream. * Generates tests for the first 5 even integers. * @return */ @TestFactory Stream<DynamicTest> dynamicTestsFromIntStream() { return IntStream.iterate(0, number -> number + 2).limit(5) .mapToObj(number -> dynamicTest("test" + number, () -> assertTrue(number % 2 == 0))); } /** * Dynamic Tests for Stream. * @return */ @TestFactory Stream<DynamicNode> dynamicTestsWithContainers() { return Stream.of("A", "B", "C") .map(inputText -> dynamicContainer("Container " + inputText, Stream.of( dynamicTest("not null", () -> assertNotNull(inputText)), dynamicContainer("properties", Stream.of( dynamicTest("length > 0", () -> assertTrue(inputText.length() > 0)), dynamicTest("not empty", () -> assertFalse(inputText.isEmpty())) )) ))); } @TestFactory DynamicNode dynamicTestFromSingleDynamicNode() { return dynamicTest("'mom' is a palindrome", () -> assertTrue(MyUtils.isPalindrome("mom"))); } /** * Dynamic Tests which returns Single DynamicNode * @return */ @TestFactory DynamicNode dynamicTestFromSingleNodeContainer() { return dynamicContainer("palindromes", Stream.of("pop", "radar", "mom", "dad") .map(inputText -> dynamicTest(inputText, () -> assertTrue(MyUtils.isPalindrome(inputText))) )); } } |
The output of the above project:
You May Also Like:
Junit 5 Architecture
JUnit 5 Annotations
JUnit 5 Maven Dependency
JUnit 5 with Gradle Dependency
JUnit 5 Test Lifecycle
JUnit 5 @BeforeAll annotation example
Unit 5 @AfterAll annotation example
JUnit 5 @BeforeEach and @AfterEach annotation Example
JUnit 5 Display Names
Assertions in JUnit 5 Examples
Third-party Assertion Libraries support in JUnit 5
JUnit 5 Assumptions Examples
Conditional Test Execution in JUnit 5
JUnit 5 Nested Tests Example
JUnit 5 @Tag Annotation example
Test Execution Order in Junit 5
Dependency Injection and Testing in JUnit 5
Test Interfaces and Default Methods in JUnit 5
That’s all about Dynamic Tests example in Junit 5
If you have any feedback or suggestion please feel free to drop in below comment box.
This is really very nice blog to learn java technology..