Android EUnit Test Application startup crash

I am trying to structure my project so that I can run EUnit tests against my code. I have 3 projects in the solution:

  1. Android Application project
  2. EUnit Test project
  3. Shared project

Any code that I want to run EUnit tests against is in the Shared project, and the Shared project is added as a reference to the Android App and EUnit Test projects. This appears to work fine until I add a dependency on a Gradle reference to my shared project. For example, in the sample project below, my Shared project has a class that extends the AndroidX library’s Fragment class. The AndroidX library (androidx.appcompat) is added as a Gradle reference to both my Android App project and my EUnit Test project, so it compiles without issue. The Android App project runs fine, but the EUnit Test project crashes at startup with error java.lang.ClassNotFoundException: androidx.fragment.lint.FragmentIssueRegistry.

It seems that the AndroidX Fragment is not actually being packaged into the APK even though it is added as a Gradle reference? Here’s the sample project.

TodoApp.zip (65.4 KB)

Where would androidx.fragment.lint.FragmentIssueRegistry be coming from? is that a package you reference? Is it packaged (ice set to copy local)? Does it show when you look whats in the .aspk, with ebuild --dump mytestproject.apk? What’s the call stack, and are you sure this exception is fatal?

I see no mention of FragmentIssueRegistry anywhere in the build log, that means this class is not being pulled in, and thus indeed will not exist at runtime. You will need to find out who/what expects it to be there… the call stack might help.

I see no mention of FragmentIssueRegistry anywhere on the internet :exploding_head: I have no idea what it is, but if I add a reference to androidx.fragment.app.Fragment in my shared code then I get the startup crash on ClassNotFoundException: androidx.fragment.lint.FragmentIssueRegistry in my Test project but not my Android application project. I’ll have to look into it some more I guess.

Looks like something related to EUnit.ContextDiscovery, which makes sense since it’s only happening in the Test project.

FATAL EXCEPTION: main
Process: org.me.tests, PID: 27426
java.lang.RuntimeException: Unable to start activity ComponentInfo{org.me.tests/org.me.tests.MainActivity}: java.lang.ClassNotFoundException: androidx.fragment.lint.FragmentIssueRegistry
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
       at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
       at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
       at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:7356)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.ClassNotFoundException: androidx.fragment.lint.FragmentIssueRegistry
       at java.lang.Class.classForName(Native Method)
       at java.lang.Class.forName(Class.java:454)
       at java.lang.Class.forName(Class.java:379)
       at RemObjects.Elements.EUnit.ContextDiscovery.ReadPackage(c:\CI\b\elements\937\Source\RemObjects.Elements.EUnit\Sources\Discovery\Android\ContextDiscovery.pas:30)
       at RemObjects.Elements.EUnit.ContextDiscovery.<init>(c:\CI\b\elements\937\Source\RemObjects.Elements.EUnit\Sources\Discovery\Android\ContextDiscovery.pas:39)
       at RemObjects.Elements.EUnit.Discovery.FromContext(c:\CI\b\elements\937\Source\RemObjects.Elements.EUnit\Sources\Discovery\Android\AndroidDiscovery.pas:16)
       at RemObjects.Elements.EUnit.Discovery.DiscoverTests(c:\CI\b\elements\937\Source\RemObjects.Elements.EUnit\Sources\Discovery\Android\AndroidDiscovery.pas:105)
       at RemObjects.Elements.EUnit.TestActivity.onCreate(c:\CI\b\elements\937\Source\RemObjects.Elements.EUnit\Sources\Android\TestActivity.pas:101)
       at org.me.tests.MainActivity.onCreate(C:\Users\mattr\Code\Elements\TodoApp\org.me.Tests\MainActivity.pas:19)
       at android.app.Activity.performCreate(Activity.java:7825)
       at android.app.Activity.performCreate(Activity.java:7814)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
       ... 11 more
Caused by: java.lang.ClassNotFoundException: androidx.fragment.lint.FragmentIssueRegistry
       at java.lang.VMClassLoader.findLoadedClass(Native Method)
       at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:738)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:363)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
       ... 24 more
Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/android/tools/lint/client/api/IssueRegistry;
       ... 24 more
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.android.tools.lint.client.api.IssueRegistry" on path: DexPathList[[zip file "/data/app/org.me.tests-iM48TuITA60FOQpvCemwKw==/base.apk"],nativeLibraryDirectories=[/data/app/org.me.tests-iM48TuITA60FOQpvCemwKw==/lib/arm64, /system/lib64, /product/lib64]]
       at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
       ... 24 more

And you’re sure this isn’t caught?

Definitely not caught. This is the “Fatal Exception” that’s crashing the app at startup every time.

let me see. looks like maybe RemObjects.Elements.EUnit.ContextDiscovery.ReadPackage just needs to catch this…

Fixed for today’s build (or if you wanna rebuild manually from GitHub).

I’d be curious to hear if how many of these happen, and if tis will be still a performance problem, if there’s potentially dozens or hundreds of these exceptions. Really curious though that it can find the class during discovery, if it’s not there… The magic of Java…

Thanks Marc. I can’t test a full build from GitHub due to the Windows key issue, but I’ll watch for it on the CI builds page. I did notice that the fix specifically looks for java.lang.ClassNotFoundException. I didn’t look at how it’s used, so I don’t know if this would be an issue – but java/Android always throws a java.lang.NoClassDefFoundError along with it. Not sure if the NoClassDefFoundError would still cause the same problem.

Ah damn, yes. Will fix (but today’s official built is already sent off, so it wont have that)

Remind me what that issue is?

Where running an EBuild that I manually built only makes it past the build phase and fails at the compile phase

Right, but EBuild != EUnit?

Ah of course lol. How do I install EUnit in a way that it gets picked up by my installed Water/EBuild?

For Android (really, everything except Toffee): easy: just build it, and drag the final .jar onto your project or References node in Water, to add a HintPath to your existing EUnit reference. it’ll then automatically use your version.

Cool, that’s easy. I am still having the same crash though…

Hm. what if you drop the on E: ... and catch all exceptions?

Ah wait, found it. The change was added to Cooper’s PackageDiscovery but needed to be in Android’s ContextDiscovery. It’s working with that change. I’ll submit a PR on GitHub.

Also, what is XCTestCase? It shows up in all my EUnit tests, but I’m not seeing where it gets added.