Search code examples
androidgradleclassloaderurlclassloadercontextclassloader

Android: after Gradle update to 6.7.1 ClassLoader in JUnit test no longer lists all resources


I need to iterate over specific classes from main package in my android unit test, to check some of their properties. For this I use standard approach, using ClassLoader:

 val classLoader = Thread.currentThread().contextClassLoader 
 val resources: Enumeration<URL> = classLoader.getResources("com/models/package")
 assert(resources.hasMoreElements()) // Fails from CL, works in AS
 

Before the Gradle update (had Gradle 5.6.4) that worked. Now the behaviour is as follows: it works when test is run from Android Studio, but fails (returns empty enumeration) when run from command line with gradlew.

I wonder what might be the difference in this respect between the two Gradle versions? And why it still works when run from Studio?

Some considerations and things I have tried:

  • Referencing these classes in unit test works ok, and also classLoader.findClass("com.models.package.MyModel") and classLoader.loadClass("com.models.package.MyModel") from unit test is working. But even after that classLoader.getResources("com/models/package") returns empty enumeration.
  • Using other references to ClassLoader, like MyModel::class.java.classLoader and ClassLoader.getSystemClassLoader() didn't make any difference.
  • Gradle build from command line contains the warning "OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended", but as far as I can tell it's not connected to my issue.
  • If I put some of the classes from 'com/models/package' to the unit test /test folder, they are getting returned in enumeration.

This might be connected with some new optimisation setting that makes ClassLoaders omit registering some of the classes, in different root directories, but as it still works in AS there might be some setting to turn this optimisation off in a command line build also?

Thank you for any suggestions on this.


Solution

  • In Gradle 6.7.1 I had to include the directory with the code to the test sourceSets. Afterwards the classloader from junit started to see the classes and return them in Enumeration.

    sourceSets {
            test {
                java.srcDirs += ['src/main']
            }
        }