Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support void class lookups in ReflectionUtils #4048

Closed
bjmi opened this issue Oct 5, 2024 · 8 comments · Fixed by #4049
Closed

Support void class lookups in ReflectionUtils #4048

bjmi opened this issue Oct 5, 2024 · 8 comments · Fixed by #4049

Comments

@bjmi
Copy link
Contributor

bjmi commented Oct 5, 2024

Running following parametrized test in JUnit 5.11

@ValueSource(strings = {
    "void", "boolean", "byte", "char", "short", "int", "long", "float", "double" })
@ParameterizedTest
void isPrimitive(Class<?> candidate) {
    assertTrue(candidate.isPrimitive());
}

only makes the "void" case fail.

org.junit.jupiter.api.extension.ParameterResolutionException:
    Error converting parameter at index 0: Failed to convert String "void" to type java.lang.Class

It looks like conversion of "void" to Class isn't supported.
Both classNameToTypeMap and primitiveToWrapperMap of org.junit.platform.commons.util.ReflectionUtils are lacking void.class and Void.class, but maybe this is by intention.

@marcphilipp
Copy link
Member

Did you deliberately not use the classes attribute?

@ValueSource(classes = { void.class, ... })
@ParameterizedTest
void isPrimitive(Class<?> candidate) {
    assertTrue(candidate.isPrimitive());
}

That being said, I see no reason not to add support for "void"

@marcphilipp marcphilipp added this to the 5.12 M1 milestone Oct 6, 2024
@sbrannen sbrannen changed the title Can't convert "void" to Class Support conversion from "void" and "Void" to Class Oct 6, 2024
@sbrannen
Copy link
Member

sbrannen commented Oct 6, 2024

Both classNameToTypeMap and primitiveToWrapperMap of org.junit.platform.commons.util.ReflectionUtils are lacking void.class and Void.class, but maybe this is by intention.

If my memory serves me correctly, it was indeed intentional since void and Void are not real types but rather pseudo-types.

And since we never had a concrete use case for supporting conversions for those in JUnit itself, we didn't introduce those mappings.

Though, I agree with @marcphilipp that it should be fine to add lookups for those in ReflectionUtils.

@bjmi
Copy link
Contributor Author

bjmi commented Oct 6, 2024

Did you deliberately not use the classes attribute?

I quickly switched to classes when strings didn't work.

marcphilipp added a commit that referenced this issue Oct 8, 2024
Both the primitive type `void` and the wrapper type `Void` are now 
supported in the internal `ReflectionUtils` to allow `String` to `Class`
conversion in parameterized tests.

Fixes #4048.

---------

Co-authored-by: Marc Philipp <mail@marcphilipp.de>
@sbrannen sbrannen changed the title Support conversion from "void" and "Void" to Class Support String conversion from void and Void to Class Jan 19, 2025
@sbrannen
Copy link
Member

sbrannen commented Jan 19, 2025

Technically speaking, "java.lang.Void" should have been converted to Class<Void> without the changes in #4049.

So, it looks like we actually made two changes.

  1. Supporting class lookups by name for "void".
  2. Supporting Void as a "wrapper" type.

Admittedly, that's a bit nuanced, but perhaps we should revise the release notes and documentation accordingly.

@sbrannen sbrannen changed the title Support String conversion from void and Void to Class Support void and Void class lookups in ReflectionUtils Jan 19, 2025
@sbrannen sbrannen self-assigned this Jan 19, 2025
@sbrannen
Copy link
Member

we should revise the release notes and documentation accordingly.

Reopening to address those concerns.

@sbrannen sbrannen reopened this Jan 19, 2025
@sbrannen
Copy link
Member

As a side note, I'm not so sure that the following should actually pass.

assertTrue(ReflectionUtils.isAssignableTo(Void.class, void.class));

Rationale: ReflectionUtils.isAssignableTo() is only supposed to be used for reflective method invocations, where the targetType (the second argument) represents a formally declared parameter type for a method or constructor. However, void is not valid as a method or constructor parameter type. Attempting to do that results in a compilation error.

In light of that, I think we should either:

  1. remove the Void.class wrapper registration, or...
  2. Modify the ReflectionUtils.isAssignableTo() methods so that false is always returned for a void targetType.

@marcphilipp, thoughts?

@sbrannen sbrannen changed the title Support void and Void class lookups in ReflectionUtils Support void class lookups in ReflectionUtils Jan 19, 2025
@sbrannen
Copy link
Member

I updated the documentation in 57e20cd, but I'm leaving this open to address the following.

In light of that, I think we should either:

1. remove the `Void.class` wrapper registration, or...
2. Modify the `ReflectionUtils.isAssignableTo()` methods so that `false` is always returned for a `void` `targetType`.

@marcphilipp
Copy link
Member

@sbrannen Good catch!

1. remove the Void.class wrapper registration

I'm in favor of removing the wrapper registration because, as you pointed out, the void type cannot be used for any kind of assignment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment