10

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

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

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

4

3 回答 3

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

然后在测试运行器中:

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
   }
}
于 2012-07-07T21:53:21.463 回答
1

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

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

ROBOLECTRIC=TRUE

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

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

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

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

于 2015-12-21T21:23:48.883 回答
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),依此类推。

于 2017-04-05T09:03:14.373 回答