= Parameter Resolution

`{ParameterResolver}` defines the `Extension` API for dynamically resolving parameters at
runtime.

If a _test class_ constructor, _test method_, or _lifecycle method_ (see
xref:writing-tests/definitions.adoc[]) declares a parameter, the parameter must be _resolved_ at
runtime by a `ParameterResolver`. A `ParameterResolver` can either be built-in (see
`{TestInfoParameterResolver}`) or xref:extensions/registering-extensions.adoc[registered by the user].
Generally speaking, parameters may be resolved by _name_, _type_, _annotation_, or any
combination thereof.

If you wish to implement a custom `{ParameterResolver}` that resolves parameters based
solely on the type of the parameter, you may find it convenient to extend the
`{TypeBasedParameterResolver}` which serves as a generic adapter for such use cases.

For concrete examples, consult the source code for `{CustomTypeParameterResolver}`,
`{CustomAnnotationParameterResolver}`, and `{MapOfListsTypeBasedParameterResolver}`.

[WARNING]
====
Due to a bug in the byte code generated by `javac` on JDK versions prior to JDK 9,
looking up annotations on parameters directly via the core `java.lang.reflect.Parameter`
API will always fail for _inner class_ constructors (e.g., a constructor in a `@Nested`
test class).

The `{ParameterContext}` API supplied to `ParameterResolver` implementations therefore
includes the following convenience methods for correctly looking up annotations on
parameters. Extension authors are strongly encouraged to use these methods instead of
those provided in `java.lang.reflect.Parameter` in order to avoid this bug in the JDK.

* `boolean isAnnotated(Class<? extends Annotation> annotationType)`
* `Optional<A> findAnnotation(Class<A> annotationType)`
* `List<A> findRepeatableAnnotations(Class<A> annotationType)`
====

[NOTE]
.Accessing the test-scoped `ExtensionContext`
====
You may override the `getTestInstantiationExtensionContextScope(...)` method to return
`TEST_METHOD` to support injecting test specific data into constructor parameters of the
test class instance. Doing so causes a test-specific `{ExtensionContext}` to be used while
resolving constructor parameters, unless the
xref:writing-tests/test-instance-lifecycle.adoc[test instance lifecycle] is set to `PER_CLASS`.
====

[TIP]
.Parameter resolution for methods called from extensions
====
Other extensions can also leverage registered `ParameterResolvers` for method and
constructor invocations, using the `{ExecutableInvoker}` available via the
`getExecutableInvoker()` method in the `ExtensionContext`.
====

[[conflicts]]
== Parameter Conflicts

If multiple implementations of `ParameterResolver` that support the same type are
registered for a test, a `ParameterResolutionException` will be thrown, with a
message to indicate that competing resolvers have been discovered. See the following
example:

.Conflicting parameter resolution due to multiple resolvers claiming support for integers
[tabs]
====
Java::
+
--
[source,java,indent=0]
----
include::example$java/example/extensions/ParameterResolverConflictDemo.java[tags=user_guide]
----
--

Kotlin::
+
--
[source,kotlin,indent=0]
----
include::example$kotlin/example/kotlin/extensions/ParameterResolverConflictDemo.kt[tags=user_guide]
----
--
====

If the conflicting `ParameterResolver` implementations are applied to different test
methods as shown in the following example, no conflict occurs.

.Fine-grained registration to avoid conflict
[tabs]
====
Java::
+
--
[source,java,indent=0]
----
include::example$java/example/extensions/ParameterResolverNoConflictDemo.java[tags=user_guide]
----
--

Kotlin::
+
--
[source,kotlin,indent=0]
----
include::example$kotlin/example/kotlin/extensions/ParameterResolverNoConflictDemo.kt[tags=user_guide]
----
--
====

If the conflicting `ParameterResolver` implementations need to be applied to the same test
method, you can implement a custom type or custom annotation as illustrated by
`{CustomTypeParameterResolver}` and `{CustomAnnotationParameterResolver}`, respectively.

.Custom type to resolve duplicate types
[tabs]
====
Java::
+
--
[source,java,indent=0]
----
include::example$java/example/extensions/ParameterResolverCustomTypeDemo.java[tags=user_guide]
----
--

Kotlin::
+
--
[source,kotlin,indent=0]
----
include::example$kotlin/example/kotlin/extensions/ParameterResolverCustomTypeDemo.kt[tags=user_guide]
----
--
====

A custom annotation makes the duplicate type distinguishable from its counterpart:

.Custom annotation to resolve duplicate types
[tabs]
====
Java::
+
--
[source,java,indent=0]
----
include::example$java/example/extensions/ParameterResolverCustomAnnotationDemo.java[tags=user_guide]
----
--

Kotlin::
+
--
[source,kotlin,indent=0]
----
include::example$kotlin/example/kotlin/extensions/ParameterResolverCustomAnnotationDemo.kt[tags=user_guide]
----
--
====

JUnit includes some built-in parameter resolvers that can cause conflicts if a resolver
attempts to claim their supported types. For example, `{TestInfo}` provides metadata about
tests. See xref:writing-tests/dependency-injection-for-constructors-and-methods.adoc[] for details. Third-party frameworks such
as Spring may also define parameter resolvers. Apply one of the techniques in this section
to resolve any conflicts.

Parameterized tests are another potential source of conflict. Ensure that tests annotated
with `@ParameterizedTest` are not also annotated with `@Test` and see
xref:writing-tests/parameterized-classes-and-tests.adoc#consuming-arguments[Consuming Arguments] for more details.
