This post talks about Argument Aggregation supports provided by JUnit Jupiter in the case of @ParameterizedTest
By default, each argument provided to a @ParameterizedTest method corresponds to a single method parameter. Consequently, argument sources that are expected to supply a large number of arguments can lead to large method signatures.
In that case, an ArgumentsAccessor may be used instead of multiple parameters. Using this API, you can access the provided arguments through a single argument passed to your test method. In addition, type conversion is supported.
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 33 34 35 36 37 |
<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>JUnit5ArgumentAggregationInParameterizedTestsExample</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> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>${junit.jupiter.version}</version> <scope>test</scope> </dependency> </dependencies> </project> |
Gender.java
1 2 3 4 5 |
package com.kkjavatutorials.model; public enum Gender { M,F } |
Person.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 |
package com.kkjavatutorials.model; import java.time.LocalDate; public class Person { private String firstName; private String lastName; private Gender gender; private LocalDate dateOfBirth; public Person(String firstName, String lastName, Gender gender, LocalDate dateOfBirth) { super(); this.firstName = firstName; this.lastName = lastName; this.gender = gender; this.dateOfBirth = dateOfBirth; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public Gender getGender() { return gender; } public LocalDate getDateOfBirth() { return dateOfBirth; } } |
CsvToPerson.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kkjavatutorials; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.junit.jupiter.params.aggregator.AggregateWith; import com.kkjavatutorials.ArgumentAggregationInParameterizedTest.PersonAggregator; @Retention(value = RetentionPolicy.RUNTIME) @Target(value = { ElementType.PARAMETER }) @AggregateWith(PersonAggregator.class) public @interface CsvToPerson { } |
ArgumentAggregationInParameterizedTest.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 |
package com.kkjavatutorials; import static org.junit.jupiter.api.Assertions.assertEquals; import java.time.LocalDate; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.aggregator.AggregateWith; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; import org.junit.jupiter.params.aggregator.ArgumentsAggregator; import org.junit.jupiter.params.provider.CsvSource; import com.kkjavatutorials.model.Gender; import com.kkjavatutorials.model.Person; public class ArgumentAggregationInParameterizedTest { /** * Argument Aggregation in ParameterizedTest * @param argumentsAccessor */ @ParameterizedTest @CsvSource({ "Jane, Doe, F, 1995-05-20", "John, Doe, M, 1995-10-22" }) void testWithArgumentsAccessor(ArgumentsAccessor argumentsAccessor) { Person person = new Person(argumentsAccessor.getString(0), argumentsAccessor.getString(1), argumentsAccessor.get(2, Gender.class), argumentsAccessor.get(3, LocalDate.class)); if (person.getFirstName().equals("Jane")) { assertEquals(Gender.F, person.getGender()); } else { assertEquals(Gender.M, person.getGender()); } assertEquals("Doe", person.getLastName()); assertEquals(1995, person.getDateOfBirth().getYear()); } /** * Custom Aggregator in in ParameterizedTest * @param person */ @ParameterizedTest @CsvSource({ "Jane, Doe, F, 1991-05-20", "John, Doe, M, 1991-10-22" }) void testWithArgumentsAggregator(@AggregateWith(PersonAggregator.class) Person person) { assertEquals("Doe", person.getLastName()); assertEquals(1991, person.getDateOfBirth().getYear()); } /** * Custom Aggregator & annotation in in ParameterizedTest * @param person */ @ParameterizedTest @CsvSource({ "Jane, Doe, F, 1992-06-22", "John, Doe, M, 1992-10-25","Sean, Doe, M, 1992-01-20" }) void testWithCustomAggregatorAnnotation(@CsvToPerson Person person) { assertEquals("Doe", person.getLastName()); assertEquals(1992, person.getDateOfBirth().getYear()); } /** * @author KK JavaTutorials * Custom Aggregator class * You should Note that an implementation of ArgumentsAggregator class must be declared as either * a topmost class or as a static inner/nested class */ public static class PersonAggregator implements ArgumentsAggregator { @Override public Person aggregateArguments(ArgumentsAccessor argumentsAccessor, ParameterContext parameterContext) { return new Person(argumentsAccessor.getString(0), argumentsAccessor.getString(1), argumentsAccessor.get(2, Gender.class), argumentsAccessor.get(3, LocalDate.class)); } } } |
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 Argument Aggregation in Parameterized Tests in Junit 5
If you have any feedback or suggestion please feel free to drop in below comment box.