Unit testing with Crosswalk and Robolectric

前提是你 提交于 2019-12-13 01:42:46

问题


We have unit tests running against our app, based on Robolectric. Some of these tests check against activities that contain WebViews.

Now we decided to use Crosswalk and, therefore, replace WebView with XWalkView in our layout XML files. But since then, the unit tests fail to run because Robolectric apparently doesn't support XWalkViews yet.

We tried writing a shadow for XWalkView, but Robolectric still calls the real implementation when inflating the content view. Other shadows (e.g. a custom WifiManager shadow) work correctly.

This is the stacktrace we encounter (code below):

android.view.InflateException: XML file build/intermediates/res/merged/debug/layout/activity_crosswalk.xml line #-1 (sorry, not yet implemented): Error inflating class org.xwalk.core.XWalkView
    at android.view.LayoutInflater.createView(LayoutInflater.java:620)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:696)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290)
    at android.app.Activity.setContentView(Activity.java:1928)
    at mycompany.myapp.test.xwalkshadow.CrosswalkActivity.onCreate(CrosswalkActivity.java:11)
    at android.app.Activity.performCreate(Activity.java:5243)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:195)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:122)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:304)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:45)
    at org.robolectric.util.ActivityController.create(ActivityController.java:118)
    at org.robolectric.util.ActivityController.create(ActivityController.java:129)
    at org.robolectric.util.ActivityController.setup(ActivityController.java:210)
    at org.robolectric.Robolectric.setupActivity(Robolectric.java:46)
    at mycompany.myapp.test.xwalkshadow.XWalkShadowRobolectricUnitTest.testInstantiation(XWalkShadowRobolectricUnitTest.java:19)
    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.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    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:152)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at android.view.LayoutInflater.$$robo$$createView(LayoutInflater.java:594)
    at android.view.LayoutInflater.createView(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$createViewFromTag(LayoutInflater.java:696)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$rInflate(LayoutInflater.java:755)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$inflate(LayoutInflater.java:492)
    at android.view.LayoutInflater.inflate(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$inflate(LayoutInflater.java:397)
    at android.view.LayoutInflater.inflate(LayoutInflater.java)
    at android.view.LayoutInflater.$$robo$$inflate(LayoutInflater.java:353)
    at android.view.LayoutInflater.inflate(LayoutInflater.java)
    at com.android.internal.policy.impl.PhoneWindow.$$robo$$setContentView(PhoneWindow.java:290)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java)
    at android.app.Activity.$$robo$$setContentView(Activity.java:1928)
    at android.app.Activity.setContentView(Activity.java)
    at mycompany.myapp.test.xwalkshadow.CrosswalkActivity.onCreate(CrosswalkActivity.java:11)
    at android.app.Activity.$$robo$$performCreate(Activity.java:5243)
    at android.app.Activity.performCreate(Activity.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:195)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:122)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:304)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:45)
    at org.robolectric.util.ActivityController.create(ActivityController.java:118)
    at org.robolectric.util.ActivityController.create(ActivityController.java:129)
    at org.robolectric.util.ActivityController.setup(ActivityController.java:210)
    at org.robolectric.Robolectric.setupActivity(Robolectric.java:46)
    at mycompany.myapp.test.xwalkshadow.XWalkShadowRobolectricUnitTest.testInstantiation(XWalkShadowRobolectricUnitTest.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    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.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    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:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    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:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    ... 1 more
Caused by: junit.framework.AssertionFailedError: Please have your activity extend XWalkActivity for shared mode
    at org.xwalk.core.XWalkCoreWrapper.initEmbeddedMode(XWalkCoreWrapper.java:189)
    at org.xwalk.core.XWalkView.reflectionInit(XWalkView.java:761)
    at org.xwalk.core.XWalkView.<init>(XWalkView.java:221)
    ... 63 more

This is the activity to be tested:

package mycompany.myapp.test.xwalkshadow;

import android.app.Activity;
import android.os.Bundle;

public class CrosswalkActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crosswalk);
    }
}

This is the layout XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="mycompany.myapp.test.xwalkshadow.CrosswalkActivity">

    <org.xwalk.core.XWalkView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </org.xwalk.core.XWalkView>
</RelativeLayout>

This is the unit test code:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;

@Config(
        sdk = 19,
        constants = BuildConfig.class,
        shadows = ShadowXWalkView.class
)
@SuppressWarnings("unused")
@RunWith(RobolectricGradleTestRunner.class)
public class XWalkShadowRobolectricUnitTest {
    @Test
    public void testInstantiation() {
        Robolectric.setupActivity(CrosswalkActivity.class);
    }
}

This is the simple shadow for XWalkView:

package mycompany.myapp.test.xwalkshadow;

import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowViewGroup;
import org.xwalk.core.XWalkView;

/**
 * Created by enrico on 14/12/15.
 */
@Implements(value = XWalkView.class, callThroughByDefault = false, isInAndroidSdk = false)
public class ShadowXWalkView extends ShadowViewGroup {
}

And this is the relevant part in build.gradle about Crosswalk and Robolectric:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    testCompile "org.robolectric:robolectric:3.0"
    testCompile 'org.robolectric:robolectric-annotations:3.0-rc3'
}

// Crosswalk
repositories {
    maven {
        url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2'
    }
}

dependencies {
    compile 'org.xwalk:xwalk_core_library:15.44.384.12'
}

Any hint is highly appreciated, thanks!

来源:https://stackoverflow.com/questions/34270884/unit-testing-with-crosswalk-and-robolectric

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!