diff --git a/junit5/README.md b/junit5/README.md index d3271caf..41b9db80 100644 --- a/junit5/README.md +++ b/junit5/README.md @@ -89,6 +89,7 @@ This default behaviour includes: * Inject into method parameters of your test methods * If the type of the parameter matches a known and resolvable bean * By default, Weld is greedy and will try to resolve all parameters which are known as bean types in the container + * An exception to this rule is `@ParameterizedTest` where Weld requires explicitly stating CDI qualifiers for each method parameter which should be injected * If this behaviour should be different, refer to [additional configuration section](#explicit-parameter-injection) * Shut down the container after test is done diff --git a/junit5/pom.xml b/junit5/pom.xml index 94605dca..3b57a056 100644 --- a/junit5/pom.xml +++ b/junit5/pom.xml @@ -31,6 +31,10 @@ org.junit.jupiter junit-jupiter-engine + + org.junit.jupiter + junit-jupiter-params + diff --git a/junit5/src/main/java/org/jboss/weld/junit5/WeldJunit5Extension.java b/junit5/src/main/java/org/jboss/weld/junit5/WeldJunit5Extension.java index e7eb603d..8ac75c94 100644 --- a/junit5/src/main/java/org/jboss/weld/junit5/WeldJunit5Extension.java +++ b/junit5/src/main/java/org/jboss/weld/junit5/WeldJunit5Extension.java @@ -58,6 +58,7 @@ import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; /** * JUnit 5 extension allowing to bootstrap Weld SE container for each @Test method (or once per test class @@ -192,7 +193,10 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon List qualifiers = resolveQualifiers(parameterContext, getContainerFromStore(extensionContext).getBeanManager()); // if we require explicit parameter injection (via global settings or annotation) and there are no qualifiers we don't resolve it - if ((getExplicitInjectionInfoFromStore(extensionContext) || (methodRequiresExplicitParamInjection(parameterContext))) + // if the method is annotated @ParameterizedTest, we treat it as explicit param injection and require qualifiers + if ((getExplicitInjectionInfoFromStore(extensionContext) + || methodRequiresExplicitParamInjection(parameterContext) + || methodIsParameterizedTest(parameterContext)) && qualifiers.isEmpty()) { return false; } else { @@ -253,6 +257,10 @@ private boolean methodRequiresExplicitParamInjection(ParameterContext pc) { return false; } + private boolean methodIsParameterizedTest(ParameterContext pc) { + return pc.getDeclaringExecutable().getAnnotation(ParameterizedTest.class) != null ? true : false; + } + private TestInstance.Lifecycle determineTestLifecycle(ExtensionContext ec) { // check the test for org.junit.jupiter.api.TestInstance annotation TestInstance annotation = ec.getRequiredTestClass().getAnnotation(TestInstance.class); diff --git a/junit5/src/test/java/org/jboss/weld/junit5/explicitInjection/parameterizedTest/Foo.java b/junit5/src/test/java/org/jboss/weld/junit5/explicitInjection/parameterizedTest/Foo.java new file mode 100644 index 00000000..8c686a9b --- /dev/null +++ b/junit5/src/test/java/org/jboss/weld/junit5/explicitInjection/parameterizedTest/Foo.java @@ -0,0 +1,15 @@ +package org.jboss.weld.junit5.explicitInjection.parameterizedTest; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class Foo { + + @Produces + String s = "fooString"; + + String ping() { + return Foo.class.getSimpleName(); + } +} diff --git a/junit5/src/test/java/org/jboss/weld/junit5/explicitInjection/parameterizedTest/ParameterizedTestExplicitInjectionTest.java b/junit5/src/test/java/org/jboss/weld/junit5/explicitInjection/parameterizedTest/ParameterizedTestExplicitInjectionTest.java new file mode 100644 index 00000000..a4f6b44e --- /dev/null +++ b/junit5/src/test/java/org/jboss/weld/junit5/explicitInjection/parameterizedTest/ParameterizedTestExplicitInjectionTest.java @@ -0,0 +1,46 @@ +package org.jboss.weld.junit5.explicitInjection.parameterizedTest; + +import java.util.Set; + +import jakarta.enterprise.inject.Default; + +import org.jboss.weld.junit5.WeldJunit5Extension; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@ExtendWith(WeldJunit5Extension.class) +public class ParameterizedTestExplicitInjectionTest { + + public static final Set strings = Set.of("one", "two", "three"); + + @ParameterizedTest + @ValueSource(strings = { "one", "two", "three" }) + public void noWeldInjection(String param) { + // String param is not resolved by Weld + Assertions.assertTrue(strings.contains(param)); + } + + // NOTE: swapping parameters in the below tests leads to a failure! Parameterized test attempts to claim the first + // parameter as its own and cast to given type; there is nothing we can do about that + @ParameterizedTest + @ValueSource(strings = { "one", "two", "three" }) + public void parameterizedTestWithWeldInjection(String param, @Default Foo foo) { + // String param is not resolved by Weld + Assertions.assertTrue(strings.contains(param)); + // Foo has explicit qualifier and Weld therefore still tried to resolve it + Assertions.assertNotNull(foo); + Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping()); + } + + @ParameterizedTest + @ValueSource(strings = { "one", "two", "three" }) + public void parameterizedTestWithTwoStringParams(String param, @Default String anotherString) { + // String param is not resolved by Weld + Assertions.assertTrue(strings.contains(param)); + // Foo has explicit qualifier and Weld therefore still tried to resolve it + Assertions.assertNotNull(anotherString); + Assertions.assertEquals("fooString", anotherString); + } +} diff --git a/pom.xml b/pom.xml index 703348aa..700338b1 100644 --- a/pom.xml +++ b/pom.xml @@ -88,6 +88,12 @@ ${version.junit.jupiter} + + org.junit.jupiter + junit-jupiter-params + ${version.junit.jupiter} + + org.junit.jupiter junit-jupiter-engine