Robolectric:测试包含来自项目依赖的视图的活动

Posted

技术标签:

【中文标题】Robolectric:测试包含来自项目依赖的视图的活动【英文标题】:Robolectric: testing activity containing view from project dependency 【发布时间】:2016-10-17 23:09:53 【问题描述】:

我正在尝试使用 Robolectric 为包含 com.google.vr.sdk.base.GvrView 的活动编写单元测试,但出现此错误:

android.view.InflateException: XML file build/intermediates/res/merged/debug/layout/activity_360_video.xml line #-1 (sorry, not yet implemented): Error inflating class com.google.vr.sdk.base.GvrView

GvrView 包含在build.gradle 中的项目中:

dependencies 
    ...
    //Google Cardboard
    compile project(':cardboardsdk:base')
    compile project(':cardboardsdk:common')

我不清楚是否无法使用 robolectric 来扩展此视图,因为 robolectric 尚未完成一些必要的实现,或者我是否只是没有正确连接所有内容。

我尝试按照here 的描述将依赖项添加到测试中:

@Config(libraries = 
    "build/intermediates/exploded-aar/<Project name>.cardboardsdk/base/1.0.0",
    "build/intermediates/exploded-aar/<Project name>.cardboardsdk/common/1.0.0"
)

但这没有任何效果。

完整的测试类:

@Config(libraries = 
    "build/intermediates/exploded-aar/<Project name>.cardboardsdk/base/1.0.0",
    "build/intermediates/exploded-aar/<Project name>.cardboardsdk/common/1.0.0"
)
public class Activity360VideoTest extends PowerRoboTest 
  Activity activity;

  @Before
  public void setup() 
    activity = Robolectric.buildActivity(Activity360Video.class).create().get();
  

  @Test
  public void test() 
    assertNotNull(activity);
  

和堆栈跟踪:

android.view.InflateException: XML file build/intermediates/res/merged/debug/layout/activity_360_video.xml line #-1 (sorry, not yet implemented): Error inflating class com.google.vr.sdk.base.GvrView

    at android.view.LayoutInflater.createView(LayoutInflater.java:633)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
    at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:284)
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
    at <package>.Activity360Video.onCreate(Activity360Video.java:52)
    at android.app.Activity.performCreate(Activity.java:5933)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:195)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:126)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:340)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:40)
    at org.robolectric.util.ActivityController.create(ActivityController.java:123)
    at org.robolectric.util.ActivityController.create(ActivityController.java:133)
    at <package>.Activity360VideoTest.setup(Activity360VideoTest.java:25)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:250)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:176)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:49)
    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:142)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:146)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:130)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at android.view.LayoutInflater.$$robo$$createView(LayoutInflater.java:607)
    at android.view.LayoutInflater.createView(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$createViewFromTag(LayoutInflater.java:743)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$rInflate(LayoutInflater.java:806)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$rInflate(LayoutInflater.java:809)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$inflate(LayoutInflater.java:504)
    at android.view.LayoutInflater.inflate(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$inflate(LayoutInflater.java:414)
    at android.view.LayoutInflater.inflate(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$inflate(LayoutInflater.java:365)
    at android.view.LayoutInflater.inflate(LayoutInflater.java)
    at android.support.v7.app.AppCompatDelegateImplV9.$$robo$$setContentView(AppCompatDelegateImplV9.java:284)
    at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java)
    at android.support.v7.app.AppCompatActivity.$$robo$$setContentView(AppCompatActivity.java:140)
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java)
    at <package>.Activity360Video.onCreate(Activity360Video.java:52)
    at android.app.Activity.$$robo$$performCreate(Activity.java:5933)
    at android.app.Activity.performCreate(Activity.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:195)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:126)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:340)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:40)
    at org.robolectric.util.ActivityController.create(ActivityController.java:123)
    at org.robolectric.util.ActivityController.create(ActivityController.java:133)
    at <package>.Activity360VideoTest.setup(Activity360VideoTest.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:250)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:176)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:49)
    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:142)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:146)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:130)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    ... 1 more
Caused by: java.lang.UnsatisfiedLinkError: no gvrbase in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at com.google.vr.sdk.base.CardboardViewNativeImpl.<init>(CardboardViewNativeImpl.java:98)
    at com.google.vr.sdk.base.ImplementationSelector.createCardboardViewApi(ImplementationSelector.java:34)
    at com.google.vr.sdk.base.GvrView.init(GvrView.java:764)
    at com.google.vr.sdk.base.GvrView.<init>(GvrView.java:255)
    ... 71 more

【问题讨论】:

【参考方案1】:

看起来 GvrView 正在静态初始化程序中加载 libgvrbase.so,但这在 Robolectric 中失败。

见:Robolectric tanks on Application objects that load JNI libraries. Can I get a workaround?

和:https://github.com/robolectric/robolectric/issues/1171

您可以尝试使用 try/catch。

【讨论】:

以上是关于Robolectric:测试包含来自项目依赖的视图的活动的主要内容,如果未能解决你的问题,请参考以下文章

robolectric 依赖库加载缓慢

Robolectric结合Android Studio的使用

Robolectric使用教程

Robolectric——Shadows 官网翻译

Robolectric——Shadows 官网翻译

Robolectric使用教程