Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Instrumentation test java.lang.UnsatisfiedLinkError on using AndroidJunitRunner and AndroidJUnit4

I am using robolectric in our unit tests. Recently in our project, we are adding a new dependency from zendesk.

repositories {

    maven {
        url 'https://zendesk.artifactoryonline.com/zendesk/repo'
    }
}

compile group: 'com.zendesk', name: 'sdk', version: '1.3.0.1'

Now we have not even referenced any class from this library and we are getting exceptions in our robolectric unit tests just by adding this dependency. I thought the problem is in our project, but its also occurring on a sample robolectric test project.

java.lang.VerifyError: Expecting a stackmap frame at branch target 31
Exception Details:
  Location:
    com/zendesk/sdk/power/BatteryStateBroadcastReceiver.onReceive(Landroid/content/Context;Landroid/content/Intent;)
V @13: ifnonnull
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: b200 1212 0703 bd00 0fb8 0015 2cc7 0012
    0x0000010: b200 1212 0303 bd00 0fb8 0017 a700 66b2
    0x0000020: 0012 bb00 1159 b700 1c12 04b6 001d 2cb6
    0x0000030: 0014 b600 1db6 001e 03bd 000f b800 1512
    0x0000040: 062c b600 14b6 001b 9900 1ab2 0012 1202
    0x0000050: 03bd 000f b800 162b b800 1804 b600 19a7
    0x0000060: 0023 1205 2cb6 0014 b600 1b99 0017 b200
    0x0000070: 1212 0103 bd00 0fb8 0016 2bb8 0018 03b6
    0x0000080: 0019 b200 1212 0803 bd00 0fb8 0015 b1  

at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.robolectric.internal.Shadow.newInstanceOf(Shadow.java:15)
at org.robolectric.shadows.ShadowApplication.registerBroadcastReceivers(ShadowApplication.java:148)
at org.robolectric.shadows.ShadowApplication.bind(ShadowApplication.java:137)
at org.robolectric.shadows.CoreShadowsAdapter.bind(CoreShadowsAdapter.java:99)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:121)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:421)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:234)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:185)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:149)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
like image 854
Kanishk Avatar asked Jun 29 '15 22:06

Kanishk


1 Answers

Found the fix for this. We were not using zendesk code in our test cases. The broadcast receivers from the added dependency(zendesk) were getting added to AndroidManifest.xml through the gradle build. The RobolectricTestRunner class parses the manifest into its internal ApplicationManifest object and then sets up application state through ShadowApplication class. The ShadowApplication class registers broadcast receivers from the application manifest. This is where I was getting the above error.

Fix: We have a custom test runner that extends RobolectricGradleTestRunner. In that I have overriden the getAppManifest method and removed the broadcast receivers not required. I know its a kind of workaround but there was no other alternative. Didn't want to create another manifest and create duplication. Here's the code snippet.

@Override
protected AndroidManifest getAppManifest(org.robolectric.annotation.Config config) {
    AndroidManifest manifest = super.getAppManifest(config);
    List<BroadcastReceiverData> broadcastReceivers = manifest.getBroadcastReceivers();
    List<BroadcastReceiverData> removeList = new ArrayList<>();
    for(BroadcastReceiverData receiverData : broadcastReceivers) {
        if(isDeletePackage(receiverData.getClassName())) {
            removeList.add(receiverData);
        }
    }
    broadcastReceivers.removeAll(removeList);
    return  manifest;
}

private boolean isDeletePackage(String className) {
    for(String s : DELETE_BROADCAST_PACKAGE) {
        if(className.startsWith(s)) {
            return true;
        }
    }
    return false;
}

The DELETE_BROADCAST_PACKAGE is simply a String hashset. Containing the package hierarchy name

like image 152
Kanishk Avatar answered Oct 19 '22 15:10

Kanishk