Skip to content

Commit

Permalink
@ExplicitParameterInjection is now by default inherited for nested cl…
Browse files Browse the repository at this point in the history
…asses
  • Loading branch information
manovotn committed Jan 19, 2024
1 parent 3b7c5a6 commit b83166d
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,26 @@
import jakarta.enterprise.inject.Default;

/**
* An annotation used to enforce explicit parameter annotation. When applied, Weld will only attempt to resolve method
* parameters which have qualifiers. In case no qualifier is required for your bean, add the {@link Default} qualifier, see CDI
* specification for in depth explanation on qualifiers.
* An annotation used to enforce explicit parameter annotation. When applied and set to {@code true}, Weld will only attempt to
* resolve method parameters which have qualifiers. In case no qualifier is required for your bean, add the {@link Default}
* qualifier, see CDI specification for in depth explanation on qualifiers.
*
* This annotation can be applied either on test class, in which case it affects parameter injection in all methods, or on
* a method.
* This annotation can be applied either on a test class, in which case it affects parameter injection in all methods, or on
* a test method.
*
* Nested classes inherit the behavior declared by their enclosing class but can re-declare this annotation along with the
* {@link #value()} parameter to override the behavior.
*
* @author <a href="mailto:[email protected]">Matej Novotny</a>
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface ExplicitParamInjection {

/**
* If set to {@code true}, Weld will only attempt to resolve parameters which have CDI qualifier annotations.
*
* @return {@code true} by default; can be explicitly set to {@code false} to make Weld attempt to resolve all parameters
*/
boolean value() default true;

}
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,22 @@ private static void storeExplicitParamResolutionInformation(ExtensionContext ec)
return;
}
// check class-level annotation
for (Annotation annotation : ec.getRequiredTestClass().getAnnotations()) {
if (annotation.annotationType().equals(ExplicitParamInjection.class)) {
setExplicitInjectionInfoToStore(ec, true);
break;
Class<?> inspectedTestClass = ec.getRequiredTestClass();
ExplicitParamInjection explicitParamInjection = inspectedTestClass.getAnnotation(ExplicitParamInjection.class);
if (explicitParamInjection != null) {
setExplicitInjectionInfoToStore(ec, explicitParamInjection.value());
} else {
// if not found, it can still be a nested class
// inspect enclosing classes until first annotation is found or until we hit top-level class
inspectedTestClass = inspectedTestClass.getEnclosingClass();
while (inspectedTestClass != null && explicitParamInjection == null) {
explicitParamInjection = inspectedTestClass.getAnnotation(ExplicitParamInjection.class);
if (explicitParamInjection != null) {
setExplicitInjectionInfoToStore(ec, explicitParamInjection.value());
}
inspectedTestClass = inspectedTestClass.getEnclosingClass();
}
}

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

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

import org.jboss.weld.junit5.basic.Foo;
import org.jboss.weld.junit5.explicitInjection.Bar;
Expand All @@ -16,7 +15,7 @@ public class ParametersAutoConfigTest {
@DisplayName("Ensure the parameters Foo and Bar are automatically included in container with no configuration")
void test(Foo foo, Bar bar) {
assertNotNull(bar);
assertNull(bar.ping());
assertEquals(Bar.class.getSimpleName(), bar.ping());
assertNotNull(foo);
assertEquals(foo.getBar(), "baz");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class Bar {
private String someText = null;

public Bar() {
this.someText = Bar.class.getSimpleName();
}

public Bar(String someText) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ public class CustomExtension implements ParameterResolver {
@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
throws ParameterResolutionException {
// dumb approach but we only ever resolve Bar anyway :)
return new Bar(CustomExtension.class.getSimpleName());
if (parameterContext.getParameter().getType().equals(Bar.class)) {
return new Bar(CustomExtension.class.getSimpleName());
} else {
throw new IllegalStateException(getClass().getName() + " can only resolve parameter Bar!");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package org.jboss.weld.junit5.explicitInjection;

import jakarta.enterprise.inject.Default;

import org.jboss.weld.junit5.ExplicitParamInjection;
import org.jboss.weld.junit5.WeldJunit5Extension;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(WeldJunit5Extension.class)
@ExplicitParamInjection(false)
public class ExplicitParameterInjectionNestedClass2Test {

@Test
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(Bar.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}

@Nested
class NestedTestClass {

@Test
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Weld will now claim all parameters as beans, even Bar
Assertions.assertNotNull(bar);
Assertions.assertEquals(Bar.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}

@Nested
class TwiceNestedTestClass1 {

@Test
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(Bar.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}
}

@Nested
@ExplicitParamInjection(true)
@ExtendWith(CustomExtension.class) // TwiceNestedTestClass2 and ThriceNestedClass will both use this
class TwiceNestedTestClass2 {

@Test
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(CustomExtension.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}

@Nested
class ThriceNestedClass {

@Test
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(CustomExtension.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.jboss.weld.junit5.explicitInjection;

import jakarta.enterprise.inject.Default;

import org.jboss.weld.junit5.ExplicitParamInjection;
import org.jboss.weld.junit5.WeldJunit5Extension;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

// Note that @ExtendWith(CustomExtension.class) has to be on each method separately. The inheritance of this would
// otherwise cause failures for TwiceNestedTestClass2 and ThriceNestedClass where Weld claims all parameters.
@ExtendWith(WeldJunit5Extension.class)
@ExplicitParamInjection(true)
public class ExplicitParameterInjectionNestedClassTest {

@Test
@ExtendWith(CustomExtension.class)
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(CustomExtension.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}

@Nested
class NestedTestClass {

@Test
@ExtendWith(CustomExtension.class)
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(CustomExtension.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}

@Nested
class TwiceNestedTestClass1 {

@Test
@ExtendWith(CustomExtension.class)
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(CustomExtension.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}
}

@Nested
@ExplicitParamInjection(false)
class TwiceNestedTestClass2 {

@Test
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// Bar should be resolved by another extension
Assertions.assertNotNull(bar);
Assertions.assertEquals(Bar.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}

@Nested
class ThriceNestedClass {

@Test
public void testParameterResolution(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) {
// NOTE: Bar should be Weld again!
Assertions.assertNotNull(bar);
Assertions.assertEquals(Bar.class.getSimpleName(), bar.ping());
// Foo should be resolved as usual
Assertions.assertNotNull(foo);
Assertions.assertEquals(Foo.class.getSimpleName(), foo.ping());
// BeanWithQualifier should be resolved
Assertions.assertNotNull(bean);
Assertions.assertEquals(BeanWithQualifier.class.getSimpleName(), bean.ping());
}
}
}
}
}

0 comments on commit b83166d

Please sign in to comment.