Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions documentation/src/docs/asciidoc/user-guide/extensions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,48 @@ constructor invocations, using the `{ExecutableInvoker}` available via the
`getExecutableInvoker()` method in the `ExtensionContext`.
====

[[extensions-parameter-resolution-conflicts]]
==== Parameter Conflicts

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

[source,java,indent=0]
.Conflicting parameter resolution due to duplicate types
----
include::{testDir}/example/extensions/ParameterResolverDuplicateTypeInteger.java[tags=user_guide]
----

If the conflicting `ParameterResolver` implementations are applied to different test
methods, the methods can be separated into <<writing-tests-nested, `nested tests`>>
as follows:

[source,java,indent=0]
.Nested parameter resolution to resolve duplicate types
----
include::{testDir}/example/extensions/ParameterResolverNestedClasses.java[tags=user_guide]
----

If the conflicting `ParameterResolver` implementations are applied within the same test
method, consider a wrapper class for the one of the conflicting types as follows:

[source,java,indent=0]
.Wrapped parameter resolution to resolve duplicate types
----
include::{testDir}/example/extensions/ParameterResolverWrappedType.java[tags=user_guide]
----

JUnit includes some built-in parameter resolvers that can cause conflicts if an attempt
is made to redefine their supported types. For example, `{TestInfo}` provides metadata
about tests. See <<writing-tests-dependency-injection>> 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
<<writing-tests-parameterized-tests-consuming-arguments>> for more details.

[[extensions-test-result-processing]]
=== Test Result Processing

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package example.extensions;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.RegisterExtension;

// tag::user_guide[]
public class ParameterResolverDuplicateTypeInteger {

@RegisterExtension
static final FirstIntegerResolver firstIntegerResolver = new FirstIntegerResolver();

@RegisterExtension
static final SecondIntegerResolver secondIntegerResolver = new SecondIntegerResolver();

@Test
void testInt(int i) {
// Test will not run due to ParameterResolutionException
assertEquals(1, i);
}

static class FirstIntegerResolver implements ParameterResolver {

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().getType() == int.class;
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return 1;
}
}

static class SecondIntegerResolver implements ParameterResolver {

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().getType() == int.class;
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return 2;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package example.extensions;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.RegisterExtension;

// tag::user_guide[]
public class ParameterResolverNestedClasses {

@Test
@DisplayName("Outer class test")
void testOuterClass(TestInfo testInfo) {
assertEquals("Outer class test", testInfo.getDisplayName());
}

@Nested
class FirstResolution {

@RegisterExtension
final FirstIntegerResolver firstIntegerResolver = new FirstIntegerResolver();

@Test
void testIntNested(int i) {
assertEquals(1, i);
}
}

@Nested
class SecondResolution {

@RegisterExtension
final SecondIntegerResolver secondIntegerResolver = new SecondIntegerResolver();

@Test
void testIntNested(int i) {
assertEquals(2, i);
}
}

static class FirstIntegerResolver implements ParameterResolver {

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().getType() == int.class;
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return 1;
}
}

static class SecondIntegerResolver implements ParameterResolver {

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().getType() == int.class;
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return 2;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package example.extensions;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.RegisterExtension;

// tag::user_guide[]
public class ParameterResolverWrappedType {

@RegisterExtension
static final FirstIntegerResolver firstIntegerResolver = new FirstIntegerResolver();

@RegisterExtension
static final SecondIntegerResolver secondIntegerResolver = new SecondIntegerResolver();

@Test
void testInt(int i, WrappedInteger wrappedInteger) {
assertEquals(1, i);
assertEquals(2, wrappedInteger.getValue());
}

static class FirstIntegerResolver implements ParameterResolver {

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().getType() == int.class;
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return 1;
}
}

static class SecondIntegerResolver implements ParameterResolver {

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().getType() == WrappedInteger.class;
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return new WrappedInteger(2);
}
}

static class WrappedInteger {

private int value;

public WrappedInteger(int value) {
this.value = value;
}

public int getValue() {
return value;
}
}
}