问题
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 XWalkView
s 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