Robolectric坦克在加载JNI库的Application对象上。我可以获得解决方法吗?

时间:2012-05-03 05:26:23

标签: android unit-testing robolectric

我的Android应用的Application对象加载了一个JNI库,而Robolectric似乎并不喜欢这样。当我去运行我的测试时,Robolectric开始疯狂,我得到了这个堆栈跟踪:

  

java.lang.UnsatisfiedLinkError:java.library.path中没有cperryinc-jni     在java.lang.ClassLoader.loadLibrary(ClassLoader.java:1758)at   java.lang.Runtime.loadLibrary0(Runtime.java:823)at   java.lang.System.loadLibrary(System.java:1045)at   com.cperryinc.application.MoolaApplication。(MoolaApplication.java:24)     at java.lang.Class.forName0(Native Method)at   java.lang.Class.forName(Class.java:169)at   com.xtremelabs.robolectric.internal.ClassNameResolver.safeClassForName(ClassNameResolver.java:36)     在   com.xtremelabs.robolectric.internal.ClassNameResolver.resolve(ClassNameResolver.java:15)     在   com.xtremelabs.robolectric.ApplicationResolver.newApplicationInstance(ApplicationResolver.java:71)     在   com.xtremelabs.robolectric.ApplicationResolver.resolveApplication(ApplicationResolver.java:28)     在   com.xtremelabs.robolectric.RobolectricTestRunner.createApplication(RobolectricTestRunner.java:483)     在   com.xtremelabs.robolectric.RobolectricTestRunner.setupApplicationState(RobolectricTestRunner.java:360)     在   com.xtremelabs.robolectric.RobolectricTestRunner.internalBeforeTest(RobolectricTestRunner.java:299)     在   com.xtremelabs.robolectric.RobolectricTestRunner.methodBlock(RobolectricTestRunner.java:277)     在   org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)     在   org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)     在   org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)     在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:193)at   org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:52)at at   org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)at at   org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:42)at at   org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:184)at at   org.junit.runners.ParentRunner.run(ParentRunner.java:236)at at   org.junit.runner.JUnitCore.run(JUnitCore.java:157)at   com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)     在   com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:182)     在   com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:62)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)     在   com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

我不确定我能做些什么。有关解决方法的任何想法吗?

3 个答案:

答案 0 :(得分:5)

解决方案适用于Robolectric 1.2,而非2。+

感谢Jan Berkel在这里回答: https://groups.google.com/d/msg/robolectric/beW9XjT8E1A/pJQrRaybN30J

class MyJniClass {
 static {
        try {
            System.loadLibrary("libname");
        } catch (UnsatisfiedLinkError e) {
            // only ignore exception in non-android env
            if ("Dalvik".equals(System.getProperty("java.vm.name"))) throw e;
        }
    }
}
  

然后在testrunner中:

public class MyTestRunner  extends RobolectricTestRunner {
   public MyTestRunner(Class testClass) throws InitializationError {
         // remove native calls + replace with shadows
        addClassOrPackageToInstrument("com.example.jni.MyJniClass");
   }

   protected void bindShadowClasses() {
         // bind shadow JNI classes
   }
}

答案 1 :(得分:1)

重量级应用程序的一个选项与Robolectric不兼容的应用程序类是创建一个空的Application对象并将其用于您的Robolectric测试:

这样的事情:

public void EmptyApp extends Application { 
}

然后您的测试设置可能如下所示:

@RunWith(RobolectricTestRunner.class)
@Config(application = EmptyApplication.class, manifest = "src/main/AndroidManifest.xml", sdk = 23)   

由于您已引用清单,因此Context#getString(int id)中仍可使用所有资源,依此类推。

答案 2 :(得分:0)

正如@Jared指出的那样,@ Christopher给出的解决方案不适用于Robolectric 2或3.

我最终使用的解决方案是添加环境变量:

ROBOLECTRIC=TRUE

到我的测试的构建配置。 (运行 - >编辑配置,环境变量)。

然后在加载有问题的库之前检查该环境变量。例如:

class MyClass {
    if(System.getenv("ROBOLECTRIC") == null) {
        System.loadLibrary("libname");
    }
}

显然,你将无法测试任何依赖于该库的代码,但至少可以进行一些测试!