[params] Use test class' classloader to load parameters #3293
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #3291.
Overview
As noted in #3291, to support varied classloader environments, the argument converter/loader logic should ideally be classloader aware. The best thing to do is to use the test class' classloader to load any classes. This PR attempts to do this.
The declaring class (and hence its classloader) is available through the
ParameterContext
(getParameter().getDeclaringExecutable().getDeclaringClass()
). However, the reference to theParameterContext
is lost in theSimpleArgumentConverter
abstraction, from whichDefaultArgumentConverter
currently inherits. Hence I have changedDefaultArgumentConverter
to implementArgumentConverter
directly. This technical represents a major (breaking) change to the packageorg.junit.jupiter.params.converter
, becauseDefaultArgumentConverter
is a public class in that package. However, because it's been annotatedINTERNAL
I don't think that that matters (any downstream users that have inherited from it probably deserve what they get... 😄).I have tried to implement it as best as I can so that if (for whatever reason) the
DefaultArgumentConverter
doesn't have access to the parameter context, then it will fall back to its current behaviour. If one is present, then it will use the test class' classloader.The implementation was complicated by the fact that
DefaultArgumentsAccessor
invokesDefaultArgumentsConverter.convert()
directly, andDefaultArgumentsAccessor
(and theArgumentsAccessor
API provides noParameterContext
. So there was no way to pass the necessary information in toconvert()
. I have added theParameterContext
as a constructor parameter toDefaultArgumentsAccessor
to work around this. It might have been cleaner (less changes to the tests) to add a second constructor instead and have the original delegate to the new one,The current implementation passes all current tests (at least, it did on my machine!) but I haven't added new tests for the enhanced class-loader-sensitive functionality as yet. I want to make sure that we're happy with this direction before I invest that time. There are a couple of different ways that this cat could be skinned (no offence to cats intended) and the interaction between the various default implementations is a bit complicated.
I hereby agree to the terms of the JUnit Contributor License Agreement.
Definition of Done
@API
annotations