Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit method parameter check if List<Person>

Tags:

java

junit5

In JUnit, I am using ParameterResolver to dynamically create and inject method argument to a Test, this works for non generic methods like the one below which is expecting Person peron. How can I instead change it to List<Person> personListand have the supportsParameter check if List is of Person

@ExtendWith({AnnotationProcessor.class})
public void testInject(Person person) {
    System.out.println(person);
}

AnnotationProcessor.java

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
        throws ParameterResolutionException {
    Parameter parameter = parameterContext.getParameter();

    return Person.class.equals(parameter.getType());
}

The closest I was able to use is :

   @Override
    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
            throws ParameterResolutionException {
        Parameter parameter = parameterContext.getParameter();

        if (parameter.getParameterizedType()!= null && List.class.equals(parameter.getType())) {
            if (parameter.getParameterizedType() instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType)parameter.getParameterizedType();
                Class<?> clazz = (Class<?>)pt.getActualTypeArguments()[0];
                if (clazz == Person.class) return true;
            }


        }

        return false;
    }
like image 617
Novice User Avatar asked Nov 21 '25 05:11

Novice User


1 Answers

Here's the annotation processor that does what you want. Your attempt was pretty close I'd say.

class AnnotationProcessor implements ParameterResolver{
    @Override
    public boolean supportsParameter(
        ParameterContext parameterContext, 
        ExtensionContext extensionContext
    ) {
        Parameter parameter = parameterContext.getParameter();

        Type type = parameter.getParameterizedType();
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            if (!parameterizedType.getRawType().equals(List.class))
                return false;
            Type firstParameterType = parameterizedType.getActualTypeArguments()[0];
            return firstParameterType.equals(Person.class);
        }

        return false;
    }

    @Override
    public Object resolveParameter(
        ParameterContext parameterContext,
        ExtensionContext extensionContext
    ) {
        return Arrays.asList(new Person(), new Person());
    }
}

How does it work?

Handling annotations through reflection is an involved task because it was added to Java as an afterthought. That's why you have to do all the instanceof type checking. Apart from that it works reliably.

Why does it work?

Type erasure does not strike in this case because type erasure only erases types from runtime objects. It does not erase types from type declarations like parameters and return types. If it did many of the funny things that libraries do with generic types would not work. There are a few bugs in the JDK regarding generic type handling together with annotations but they'll only get you if you go for esoteric stuff like "annotations on type parameters in innner non static classes". For straightforward uses like yours everything should be fine.

like image 55
johanneslink Avatar answered Nov 23 '25 21:11

johanneslink



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!