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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With