Robolectric unit test help with a third party library

233 views
Skip to first unread message

Kanishk Tripathi

unread,
Jun 30, 2015, 7:24:54 AM6/30/15
to robol...@googlegroups.com

Hi,

We are 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)

-- 

Michael Grafton

unread,
Jun 30, 2015, 11:12:18 AM6/30/15
to robol...@googlegroups.com
What version of Robolectric are you using, and what JDK (and Java version)? I have a vague recollection that Robolectric was not compatible with JDK 7 or 8 at some point, and these StackMap errors were the symptom...

-- 

--
You received this message because you are subscribed to the Google Groups "Robolectric" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robolectric...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kanishk Tripathi

unread,
Jul 1, 2015, 3:51:39 PM7/1/15
to robol...@googlegroups.com
We are using robolectric 3.0-rc3, JDK 8. The tests were working fine. They are breaking on adding the new dependecy. 
Anyways I have found a fix. 

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.

Reply all
Reply to author
Forward
0 new messages