问题
I am starting to use Robolectric in Android Studio. At first I wanted to create a simple test using hamcrest, which is shown below:
@RunWith(CustomTestRunner.class)
@Config(emulateSdk = 18)
public class MainActivityTest {
private MainActivity mainActivity;
@Test
public void testMainActivity() {
mainActivity = buildActivity(MainActivity.class).create().get();
assertThat(mainActivity, notNullValue());
}
}
When executing the test throws the following exception:
java.lang.ClassCastException: java.lang.NoSuchMethodError cannot be cast to java.lang.RuntimeException
at org.robolectric.internal.ReflectionHelpers.callInstanceMethodReflectively(ReflectionHelpers.java:68)
at org.robolectric.util.ActivityController$1.run(ActivityController.java:115)
at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:268)
at org.robolectric.util.ActivityController.create(ActivityController.java:111)
at org.robolectric.util.ActivityController.create(ActivityController.java:122)
at com.enprodo.wakemethere.googleservices.geofence.GeofenceTest.testReceiver(GeofenceTest.java:31)
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:236)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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:158)
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:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
The CustomTestRunner
class looks like this:
public class CustomTestRunner extends RobolectricTestRunner {
public CustomTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
@Override
protected AndroidManifest getAppManifest(Config config) {
String manifestProperty = System.getProperty("android.manifest");
if (config.manifest().equals(Config.DEFAULT) && manifestProperty != null) {
String resProperty = System.getProperty("android.resources");
String assetsProperty = System.getProperty("android.assets");
AndroidManifest androidManifest = new AndroidManifest(
Fs.fileFromPath(manifestProperty),
Fs.fileFromPath(resProperty),
Fs.fileFromPath(assetsProperty));
androidManifest.setPackageName("com.package");
return androidManifest;
}
return super.getAppManifest(config);
}
}
I can add that MainActivity extends android.support.v7.app.ActionBarActivity
but I have no idea if that affects the behaviour.
After some digging in the Robolectric source it appears the error appears when this is executed:
ReflectionHelpers.callInstanceMethodReflectively(component, "performCreate", new ReflectionHelpers.ClassParameter(Bundle.class, bundle));
The code of callInstanceMethodReflectively
looks like this:
public static <R> R callInstanceMethodReflectively(final Object instance, final String methodName, ClassParameter... classParameters) {
try {
final Class[] classes = ClassParameter.getClasses(classParameters);
final Object[] values = ClassParameter.getValues(classParameters);
return traverseClassHierarchy(instance.getClass(), NoSuchMethodException.class, new InsideTraversal<R>() {
@Override
public R run(Class traversalClass) throws Exception {
Method declaredMethod = traversalClass.getDeclaredMethod(methodName, classes);
declaredMethod.setAccessible(true);
return (R) declaredMethod.invoke(instance, values);
}
});
} catch (InvocationTargetException e) {
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
I am not a reflection expert, but it seems that somehow the performCreate method cannot be found. Has anyone encountered similar issue? Does anyone have any idea what could be the problem?
回答1:
After some more digging it appears that with Robolectric 2.4 some issues with ActionBarActivity
appear. According to this issue full support for appcompat-v7
will be provided in Robolectric 3.0. Indeed trying Robolectric 3.0-SNAPSHOT solved the issue.
来源:https://stackoverflow.com/questions/28110031/robolectric-2-4-nosuchmethoderror-cannot-be-cast-to-runtimeexception-when-creati