Skip to content

Commit f05bb52

Browse files
committed
Improve documentation of custom implementations for parameterized tests
This commit documents that custom implementations of APIs must be either top-level or static nested classes. This commit also ensures code listings for example implementations are separated if appropriate.
1 parent 2529ceb commit f05bb52

File tree

2 files changed

+46
-13
lines changed

2 files changed

+46
-13
lines changed

documentation/src/docs/asciidoc/user-guide/writing-tests.adoc

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -983,13 +983,20 @@ primitive type.
983983
[[writing-tests-parameterized-tests-sources-ArgumentsSource]]
984984
===== @ArgumentsSource
985985

986-
`@ArgumentsSource` can be used to specify a custom, reusable `ArgumentsProvider`.
986+
`@ArgumentsSource` can be used to specify a custom, reusable `ArgumentsProvider`. Note
987+
that an implementation of `ArgumentsProvider` must be declared as either a top-level
988+
class or as a `static` nested class.
987989

988990
[source,java,indent=0]
989991
----
990992
include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsSource_example]
991993
----
992994

995+
[source,java,indent=0]
996+
----
997+
include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsProvider_example]
998+
----
999+
9931000

9941001
[[writing-tests-parameterized-tests-argument-conversion]]
9951002
==== Argument Conversion
@@ -1072,7 +1079,8 @@ method_ or a _factory constructor_ as defined below.
10721079
accepts a single `String` argument and returns an instance of the target type. The name
10731080
of the method can be arbitrary and need not follow any particular convention.
10741081
- __factory constructor__: a non-private constructor in the target type that accepts a
1075-
single `String` argument.
1082+
single `String` argument. Note that the target type must be declared as either a
1083+
top-level class or as a `static` nested class.
10761084

10771085
NOTE: If multiple _factory methods_ are discovered, they will be ignored. If a _factory
10781086
method_ and a _factory constructor_ are discovered, the factory method will be used
@@ -1087,18 +1095,29 @@ as the title of the book.
10871095
include::{testDir}/example/ParameterizedTestDemo.java[tags=implicit_fallback_conversion_example]
10881096
----
10891097

1098+
[source,java,indent=0]
1099+
----
1100+
include::{testDir}/example/ParameterizedTestDemo.java[tags=implicit_fallback_conversion_example_Book]
1101+
----
1102+
10901103
[[writing-tests-parameterized-tests-argument-conversion-explicit]]
10911104
===== Explicit Conversion
10921105

10931106
Instead of relying on implicit argument conversion you may explicitly specify an
10941107
`ArgumentConverter` to use for a certain parameter using the `@ConvertWith` annotation
1095-
like in the following example.
1108+
like in the following example. Note that an implementation of `ArgumentConverter` must be
1109+
declared as either a top-level class or as a `static` nested class.
10961110

10971111
[source,java,indent=0]
10981112
----
10991113
include::{testDir}/example/ParameterizedTestDemo.java[tags=explicit_conversion_example]
11001114
----
11011115

1116+
[source,java,indent=0]
1117+
----
1118+
include::{testDir}/example/ParameterizedTestDemo.java[tags=explicit_conversion_example_ToStringArgumentConverter]
1119+
----
1120+
11021121
Explicit argument converters are meant to be implemented by test and extension authors.
11031122
Thus, `junit-jupiter-params` only provides a single explicit argument converter that may
11041123
also serve as a reference implementation: `JavaTimeArgumentConverter`. It is used via the
@@ -1139,13 +1158,20 @@ _aggregators_.
11391158
To use a custom aggregator simply implement the `{ArgumentsAggregator}` interface and
11401159
register it via the `@AggregateWith` annotation on a compatible parameter in the
11411160
`@ParameterizedTest` method. The result of the aggregation will then be provided as an
1142-
argument for the corresponding parameter when the parameterized test is invoked.
1161+
argument for the corresponding parameter when the parameterized test is invoked. Note
1162+
that an implementation of `ArgumentsAggregator` must be declared as either a top-level
1163+
class or as a `static` nested class.
11431164

11441165
[source,java,indent=0]
11451166
----
11461167
include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsAggregator_example]
11471168
----
11481169

1170+
[source,java,indent=0]
1171+
----
1172+
include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsAggregator_example_PersonAggregator]
1173+
----
1174+
11491175
If you find yourself repeatedly declaring `@AggregateWith(MyTypeAggregator.class)` for
11501176
multiple parameterized test methods across your codebase, you may wish to create a custom
11511177
_composed annotation_ such as `@CsvToMyType` that is meta-annotated with
@@ -1157,6 +1183,11 @@ action with a custom `@CsvToPerson` annotation.
11571183
include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsAggregator_with_custom_annotation_example]
11581184
----
11591185

1186+
[source,java,indent=0]
1187+
----
1188+
include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsAggregator_with_custom_annotation_example_CsvToPerson]
1189+
----
1190+
11601191

11611192
[[writing-tests-parameterized-tests-display-names]]
11621193
==== Customizing Display Names

documentation/src/test/java/example/ParameterizedTestDemo.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,15 @@ void testWithArgumentsSource(String argument) {
201201

202202
// end::ArgumentsSource_example[]
203203
static
204-
// tag::ArgumentsSource_example[]
204+
// tag::ArgumentsProvider_example[]
205205
public class MyArgumentsProvider implements ArgumentsProvider {
206206

207207
@Override
208208
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
209209
return Stream.of("foo", "bar").map(Arguments::of);
210210
}
211211
}
212-
// end::ArgumentsSource_example[]
212+
// end::ArgumentsProvider_example[]
213213

214214
// tag::ParameterResolver_example[]
215215
@BeforeEach
@@ -246,7 +246,7 @@ void testWithImplicitFallbackArgumentConversion(Book book) {
246246

247247
// end::implicit_fallback_conversion_example[]
248248
static
249-
// tag::implicit_fallback_conversion_example[]
249+
// tag::implicit_fallback_conversion_example_Book[]
250250
public class Book {
251251

252252
private final String title;
@@ -263,7 +263,7 @@ public String getTitle() {
263263
return this.title;
264264
}
265265
}
266-
// end::implicit_fallback_conversion_example[]
266+
// end::implicit_fallback_conversion_example_Book[]
267267

268268
// @formatter:off
269269
// tag::explicit_conversion_example[]
@@ -277,7 +277,7 @@ void testWithExplicitArgumentConversion(
277277

278278
// end::explicit_conversion_example[]
279279
static
280-
// tag::explicit_conversion_example[]
280+
// tag::explicit_conversion_example_ToStringArgumentConverter[]
281281
public class ToStringArgumentConverter extends SimpleArgumentConverter {
282282

283283
@Override
@@ -286,7 +286,7 @@ protected Object convert(Object source, Class<?> targetType) {
286286
return String.valueOf(source);
287287
}
288288
}
289-
// end::explicit_conversion_example[]
289+
// end::explicit_conversion_example_ToStringArgumentConverter[]
290290

291291
// tag::explicit_java_time_converter[]
292292
@ParameterizedTest
@@ -337,7 +337,7 @@ void testWithArgumentsAggregator(@AggregateWith(PersonAggregator.class) Person p
337337

338338
// end::ArgumentsAggregator_example[]
339339
static
340-
// tag::ArgumentsAggregator_example[]
340+
// tag::ArgumentsAggregator_example_PersonAggregator[]
341341
public class PersonAggregator implements ArgumentsAggregator {
342342
@Override
343343
public Person aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) {
@@ -347,7 +347,7 @@ public Person aggregateArguments(ArgumentsAccessor arguments, ParameterContext c
347347
arguments.get(3, LocalDate.class));
348348
}
349349
}
350-
// end::ArgumentsAggregator_example[]
350+
// end::ArgumentsAggregator_example_PersonAggregator[]
351351
// @formatter:on
352352

353353
// @formatter:off
@@ -360,13 +360,15 @@ public Person aggregateArguments(ArgumentsAccessor arguments, ParameterContext c
360360
void testWithCustomAggregatorAnnotation(@CsvToPerson Person person) {
361361
// perform assertions against person
362362
}
363+
// end::ArgumentsAggregator_with_custom_annotation_example[]
363364

365+
// tag::ArgumentsAggregator_with_custom_annotation_example_CsvToPerson[]
364366
@Retention(RetentionPolicy.RUNTIME)
365367
@Target(ElementType.PARAMETER)
366368
@AggregateWith(PersonAggregator.class)
367369
public @interface CsvToPerson {
368370
}
369-
// end::ArgumentsAggregator_with_custom_annotation_example[]
371+
// end::ArgumentsAggregator_with_custom_annotation_example_CsvToPerson[]
370372
// @formatter:on
371373

372374
// tag::custom_display_names[]

0 commit comments

Comments
 (0)