app-bundle-samples
app-bundle-samples copied to clipboard
Tests in dynamic feature module fail when run through gradle command line
I wrote some tests for a Dynamic Feature Module inside DynamicFeature/src/test/java/my/package/MyTest.kt
. These tests rely on a class that is hosted in the main app
module. If I run the tests using the Android Studio configuration they run without problems, but on the other hand if I use ./gradlew test
they fail saying that the class on the main module can't be found:
java.lang.NoClassDefFoundError
Caused by: java.lang.ClassNotFoundException
In order to include the tests inside my CI, I would need either to know how to get the command line order that Android Studio is using, or figure out why when running the gradle task, it is not able to find the main module app.
Any help appreciated. Thanks in advance!
I have the same problem and I also haven't found the solution.
I'm facing the same issue as well. In my case code is in a common module shared by app and feature modules.
Full message is:
com.kouzoh.mercari.... > initializationError FAILED
java.lang.NoClassDefFoundError
Caused by: java.lang.ClassNotFoundException
Junit report:
java.lang.NoClassDefFoundError: Lcom/kouzoh/mercari/...;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
at java.lang.Class.getDeclaredFields(Class.java:1916)
at org.junit.runners.model.TestClass.getSortedDeclaredFields(TestClass.java:77)
at org.junit.runners.model.TestClass.scanAnnotatedMembers(TestClass.java:70)
at org.junit.runners.model.TestClass.<init>(TestClass.java:57)
at org.junit.runners.ParentRunner.createTestClass(ParentRunner.java:88)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:83)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
...
Caused by: java.lang.ClassNotFoundException: com.kouzoh.mercari...
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
I have the same issue, no solution yet.
Interesting,making a project that Google wont accept. I had not expected that anyway and i thougth that is possible to make something without going to Google.
Upgrading to com.android.tools.build:gradle:3.5.0 causes instrumentation tests in my dynamic feature modules to crash. Reverting back to 3.4.2 is the only solution I can find at the moment. Is this a known issue?
Anyone has the solution for this issue?
I have the same issue, no solution yet. Any solution? please?
@luisansal I currently do such things:
- make sure the DFMs have the same Gradle setting as the App module.
- make sure the DFMs can access the classes of the App Module.
Then it works when I run the Gradle CLI
Another thought is: Maybe we can create interfaces in the App Module and implement these interfaces in DFMs, but that depends on how your project structures.
Hi Mr Wang,
App Module classes, not found from other dynamic feature module (auth in my case), when run:
./gradlew auth:test:
I did the same gradle settings as the App module, but that doesn't work for me.
Team another solution?.
@wangchauyan Can you please, share a part of your gradle code config, or ./gradlew command line?
@luisansal
Hi,
Sorry, I can't share the code snap for you because it's internal codebase.
Here are my understanding of your situation and possible solutions,
I think your situation is that you have some classes in the App module.
And your DFM (let's say auth
) use these classes from the App module.
You can write the test cases in auth
module and import these classes from the App module.
But, when running the test case in auth
module, you might sometimes encounter a few issues.
- Can't resolve the supertype of the class in the App module
-> This means you might need to have the same Gradle implementation in your
auth
module cause the App module depends on some libraries. - NoClassDefFoundError
-> This means you might need to separate these shared classes out from the App module to a shared module for example, and you might need to create a jar file for your
auth
module or you can try something like this :
testImplementation project(path: ':App', configuration: 'tests')
in your auth
module.
Hope this helps.
The code under test needs to be accessible from the dynamic feature module's (DFM) test classes.
To enable this it either has to be in the DFM or included using androidTest(Implementation|Api)
. A way to keep it reusable throughout and not hard wire it to the DFM is to create a com.android.library
module and depend on that.
It would be nice to get a complete explanation of why this issue occurs. Android Studio can run the DFM tests without issue, and it seems to be manually passing the classpaths as CLI arguments. While refactoring code into a separate library module might fix it, in some cases this is a non-trivial task. We should not need to refactor significant amounts of our codebase just to be able to duplicate IDE functionality in a CI environment.
cc @jeffchang5
@masterjefferson Can you please let me know which versions of Android Studio & build tools you're using for this?
@keyboardsurfer I have tried both AS 3.5.3 and 3.6.0 RC 1 (with respective gradle plugin versions)
Build tools is 29.0.2, but also occurs with 28.0.3.
Gradle wrapper is using version 5.6.4.
Same issue for me. Feature module tests fail with NoClassDefFoundError
when running them in terminal on local machine or in CI. Tests pass in Android Studio.
I'm using AS 3.5.3, build tools 29.0.2, Gradle 5.6.4
We're currently in the progress of testing a fix for this issue.
This issue has been fixed and will be rolled out in one of the next Android Studio 4.0 canary releases.
@keyboardsurfer is this hot-patchable to 3.6? we are having to disable tests in feature modules because of this.
Hi @chrisjenx! Unfortunately this can't be easily patched as there were major changes. Thus the version code change from 3.x to 4.x.
Your best call is to upgrade to 4.x once you're ready for it or have two versions run in parallel.
@keyboardsurfer I just updated my project to Android Studio 4 and 4.0.0-beta01
gradle plugin and am still seeing NoClassDefFoundError
s related to FragmentDirections
- the generated NavDirections
for my fragment which is located in a dynamic feature module
I only see this error when executing tests via the command line
It should be okay from beta02. I am on 4.1 Canary 2 and things work well here.
@MagsMagnoli I think it helps you
// This "test" source set is a fix for SafeArgs classes not being available when running Unit tests from cmd
// See: https://issuetracker.google.com/issues/139242292
sourceSets {
getByName("test").java.srcDir("${project.rootDir}/app/build/generated/source/navigation-args/debug")
}
There was another regression in the canaries. It has been resolved and should be shipped with Canary 6.
i am currently dealing with this problem, nothing is working out
@thapelo96 Can you confirm that the issue is reproducible when running ./gradlew connectedAndroidTest --no-parallel
using the sample code?
I have the same issue on AS 4.0 even using this configuration:
testRuntimeOnly(files("$projectDir$"/../app/build/intermediates/app_classes/debug/classes.jar"))
I have tried AS 4.1 Canary 10 and I have checked it works.
Is there any way to make it work on AS 4.0?
I have the same issue on AS 4.0 even using this configuration:
testRuntimeOnly(files("$projectDir$"/../app/build/intermediates/app_classes/debug/classes.jar"))
I have tried AS 4.1 Canary 10 and I have checked it works.
Is there any way to make it work on AS 4.0?
My fault! I have missed to add another dynamic feature with the testRuntimeOnly
way. So, I have something like this:
testRuntimeOnly(files("$projectDir$"/../app/build/intermediates/app_classes/debug/classes.jar"))
testRuntimeOnly(files("$projectDir$"/../<dynamicFeatureName>/build/intermediates/app_classes/debug/classes.jar"))
I am still seeing this error Caused by: java.lang.ClassNotFoundException:
on AS 4.2 Canary 4
I am still seeing this error
Caused by: java.lang.ClassNotFoundException:
on AS 4.2 Canary 4
It has to be resolved at Canary 6.
I have the same issue on AS 4.0 even using this configuration:
testRuntimeOnly(files("$projectDir$"/../app/build/intermediates/app_classes/debug/classes.jar"))
I have tried AS 4.1 Canary 10 and I have checked it works. Is there any way to make it work on AS 4.0?My fault! I have missed to add another dynamic feature with the
testRuntimeOnly
way. So, I have something like this:testRuntimeOnly(files("$projectDir$"/../app/build/intermediates/app_classes/debug/classes.jar"))
testRuntimeOnly(files("$projectDir$"/../<dynamicFeatureName>/build/intermediates/app_classes/debug/classes.jar"))
For those still want to use 4.0
to supports product flavours
Modify the code into
testRuntimeOnly(files("$projectDir$"/../<baseApp>/build/intermediates/app_classes/<buildVariant>/classes.jar"))
testRuntimeOnly(files("$projectDir$"/../<dynamicFeatureName>/build/intermediates/app_classes/<buildVariant>/classes.jar")
Also make sure for /../
to have a correct path.
E.g with below directory structures:
|baseApp
|features
|--------/dynamicFeatureName
// needs to `cd` change directory twice to parent
testRuntimeOnly(files("$projectDir$"/../../<baseApp>/build/intermediates/app_classes/<buildVariant>/classes.jar"))
testRuntimeOnly(files("$projectDir$"/../../<dynamicFeatureName>/build/intermediates/app_classes/<buildVariant>/classes.jar")
Not working for me even in Android Studio 4.2 Canary 7..
Also tried on AS 4.0.1 by adding the below line, but no luck testRuntimeOnly(files("$projectDir/../app/build/intermediates/app_classes/internalDebug/classes.jar")) testRuntimeOnly(files("$projectDir/../<dynamicFeatureName>/build/intermediates/app_classes/internalDebug/classes.jar"))
The error is same: Unresolved reference: BaseTest (Trying to refer BaseTest present in app inside the dfm's tests)
Please help here
I am still seeing this error
Caused by: java.lang.ClassNotFoundException:
on AS 4.2 Canary 4It has to be resolved at Canary 6.
I tried the Android Studio 4.2 Canary 7 as well, still doesn't work.
Not working for me even in Android Studio 4.2 Canary 7..
Also tried on AS 4.0.1 by adding the below line, but no luck testRuntimeOnly(files("$projectDir/../app/build/intermediates/app_classes/internalDebug/classes.jar")) testRuntimeOnly(files("$projectDir/..//build/intermediates/app_classes/internalDebug/classes.jar"))
The error is same: Unresolved reference: BaseTest (Trying to refer BaseTest present in app inside the dfm's tests)
Please help here
You can't refer to test classes in another modules tests - that's not related to this issue. (I'm guessing your BaseTest is in app/src/tests
and your accessing it via dfm/src/tests
?)
@keyboardsurfer is there a new issue for this? As it shouldn't really be closed?
FYI for all of those struggling with this workaround:
For library classes the path is different
testRuntimeOnly(files("${projectDir}/../../<library module path>/build/intermediates/compile_library_classes_jar/< buildVariant >/classes.jar"))
I do not see this issue affecting the sample at hand.
Executing both ./gradlew test
or ./gradlew connectedAndroidTest
from within the DynamicFeatures
project does not yield any failed tests.
In order to see what the actual issue is, I would have to see it either being reproducible in one of the samples in this repository or with a MCVE.
Adding the line below to the dynamic feature module gradle file solved the issue on AS 4.1.1 (STABLE) Anyone knows whether the issue has been solved on any AS canary builds?
testRuntimeOnly(files("$projectDir/../app/build/intermediates/app_classes/<buildVariant>/classes.jar"))