2015-06-29 2 views
4

Я использую robolectric в наших модульных тестах. Недавно в нашем проекте мы добавили новую зависимость от zendesk.Android Instrumentation test java.lang.UnsatisfiedLinkError при использовании AndroidJunitRunner и AndroidJUnit4

repositories { 

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

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

Теперь мы даже не ссылаться любой класс из этой библиотеки, и мы получаем исключения в наших robolectric модульных тестов, просто добавив эту зависимость. Я думал, что проблема в нашем проекте, но она также встречается на образцовом проекте испытаний robolectric.

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) 
+0

Вы можете проверить окончательный AndroidManifest? Я предполагаю, что библиотека добавляет к нему какой-то широковещательный приемник. Но пока я не знаю, как это исправить –

ответ

6

Обнаружено исправление для этого. Мы не использовали код zendesk в наших тестовых случаях. Широковещательные приемники из добавленной зависимости (zendesk) добавлялись в AndroidManifest.xml через сборку gradle. Класс RobolectricTestRunner анализирует манифест в свой внутренний объект ApplicationManifest и затем устанавливает состояние приложения через класс ShadowApplication. Класс ShadowApplication регистрирует широковещательные приемники из манифеста приложения. Вот где я получил ошибку выше.

Fix: У нас есть пользовательский тестовый бегун, который расширяет RobolectricGradleTestRunner. В том, что я переопределил метод getAppManifest и удалил широковещательные приемники. Я знаю, что это своего рода обходной путь, но альтернативы не было. Не хотел создавать другой манифест и создавать дублирование. Вот фрагмент кода.

@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; 
} 

DELETE_BROADCAST_PACKAGE - просто хешсет строки. Содержит имя иерархии пакетов