-
Notifications
You must be signed in to change notification settings - Fork 233
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
Restrict scanning for concrete types over specific packages #471
Comments
I would propose something slightly different, in the end. Introduce a new interface in the API: /**
* Interface describing the API to resolve concrete types for a given abstract type.
*
* For example, a resolver which resolves all {@link java.util.List} to {@link java.util.ArrayList},
* and delegates other types to the default resolver:
*
* <pre>{@code
* public class ListConcreteTypeResolver implements ConcreteTypeResolver {
* <T> List<Class<?>> getPublicConcreteSubTypesOf(final Class<T> type) {
* if (List.class.equals(type)) {
* return ArrayList.class;
* }
*
* return ConcreteTypeResolver.defaultConcreteTypeResolver().getPublicConcreteSubTypesOf(type);
* }
* }
* }</pre>
*/
@FunctionalInterface
public interface ConcreteTypeResolver {
/**
* Returns a list of concrete types for the given {@code type}.
*
* @param type the abstract type to resolve
* @param <T> the actual type to introspect
* @return a list of all concrete subtypes to use
*/
<T> List<Class<?>> getPublicConcreteSubTypesOf(final Class<T> type);
/**
* @return a default concrete type resolver which will scan the whole classpath for concrete types
*/
static ConcreteTypeResolver defaultConcreteTypeResolver() {
return ReflectionUtils::getPublicConcreteSubTypesOf;
}
} This interface's default implementation is then the current type scanning mechanism, i.e. the one which relies on I'll open a PR, let me know what you think. I know technically this is a new feature, and I understand the project is in maintenance mode, but I hope it's small enough you might consider it 🙂 |
For those wondering, the current workaround is to register a randomizer for every abstract type, mapping to a list of known concrete types. So you could reuse final CustomRandomizerRegistry randomizerRegistry = new CustomRandomizerRegistry();
final EasyRandom random = new EasyRandom(new EasyRandomParameters().randomizerRegistry(randomizerRegistry));
// the .. at the end specifies to look at all sub-packages as well
final ScanResult result = new ClassGraph().acceptPackages("com.acme.super.cool.package..").scan();
// scan all interfaces; this doesn't include abstract classes, but it shouldn't be hard to add
result.getAllInterfaces().forEach(abstractInfo -> {
// look at all concrete classes directly implementing this interface
abstractInfo
.getClassesImplementing()
.filter(ClassInfo::isStandardClass)
.filter(info -> !info.isAbstract())
.directOnly()
.forEach(concreteInfo -> {
randomizerRegistry.registerRandomizer(
abstractInfo.loadClass(),
concreteInfo.loadClass(abstractInfo.loadClass())
);
});
});
// this will create an instance of MyConcreteType
final MyAbstractType instance = random.nextObject(MyAbstractType.class); The downside with this workaround is that you rely on the custom randomizers referring to the |
Class scanning is a great feature, but depending on the size of your project, it leads to some minor issues. For example, I'd like to use
EasyRandom
as part of the test harness for a project. The test harness has its own module as it gets included into different module. Scanning for types may end up finding different implementations of the interfaces depending on the module in which the test harness is pulled. I'm sure that's a nice use case for some, but it can also lead to some issues. For example, the test harness module already pulls in a dependency which has concrete implementations of some types. These are beans and can easily be generated byEasyRandom
. However, maybe in another module, there are other implementations which run into limitations ofEasyRandom
, or which aren't strictly beans. In this case, it would be great if I could specify which implementations to use.Secondly, scanning the whole class path can be prohibitively expensive. This isn't a big overhead when running a complete test suite, but when running single tests in your IDE having it add a few seconds for a test which takes 5 milliseconds is a bit tedious.
Now, neither are blockers, but restricting the scanning to specific packages seems like a pretty easy fix - this is already supported by
ClassGraph
, and it would fix both issues.Let me know if I wasn't clear. If this is something you'd consider, I'm also happy opening the PR myself.
The text was updated successfully, but these errors were encountered: