Reputation: 5806
I'm testing my android App with Robolectric and I'm struggling with this cast :
MyModel myModel = ((MyApplication) context.getApplicationContext()).getMyModel;
Apparently Robolectric is complaining with this error:
java.lang.RuntimeException: java.lang.ClassCastException: android.app.Application cannot be cast to com.reply.delhaize.common.DelhaizeApplication
at org.robolectric.util.SimpleFuture.run(SimpleFuture.java:57)
at org.robolectric.shadows.ShadowAsyncTask$2.run(ShadowAsyncTask.java:95)
at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:37)
at org.robolectric.util.Scheduler.post(Scheduler.java:42)
at org.robolectric.shadows.ShadowAsyncTask.execute(ShadowAsyncTask.java:92)
at android.os.AsyncTask.execute(AsyncTask.java)
at com.reply.delhaize.common.models.StoreModel.getStoreList(StoreModel.java:617)
at com.reply.delhaize.common.models.StoreModel.fetchAllStores(StoreModel.java:107)
at com.reply.delhaize.core.tests.storefinder.StoreFinderTest.fetchAllStoresWhenWifiIsOn(StoreFinderTest.java:84)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:234)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:175)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.reply.delhaize.common.DelhaizeApplication
at com.my.package.name.models.GetApiModelTaskOtto.doInBackground(GetApiModelTaskOtto.java:74)
at com.my.package.name.models.GetApiModelTaskOtto.doInBackground(GetApiModelTaskOtto.java:1)
at android.os.ShadowAsyncTaskBridge.doInBackground(ShadowAsyncTaskBridge.java:14)
at org.robolectric.shadows.ShadowAsyncTask$BackgroundWorker.call(ShadowAsyncTask.java:149)
at org.robolectric.util.SimpleFuture.run(SimpleFuture.java:52)
at org.robolectric.shadows.ShadowAsyncTask$2.run(ShadowAsyncTask.java:95)
at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:37)
at org.robolectric.util.Scheduler.post(Scheduler.java:42)
at org.robolectric.shadows.ShadowAsyncTask.execute(ShadowAsyncTask.java:92)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.robolectric.bytecode.ShadowWrangler$ShadowMethodPlan.run(ShadowWrangler.java:456)
at android.os.AsyncTask.execute(AsyncTask.java)
at com.my.package.name.models.StoreModel.getStoreList(StoreModel.java:617)
at com.my.package.name.models.StoreModel.fetchAllStores(StoreModel.java:107)
at com.reply.delhaize.core.tests.storefinder.StoreFinderTest.fetchAllStoresWhenWifiIsOn(StoreFinderTest.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
... 22 more
I would like to find a proper way to test it.
I have declared MyApplication in the manifest:
<application
android:name="com.my.package.name.MyApplication"
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
......
and these are the tests
@RunWith(RoboletricTestRunner.class)
public class StoreFinderTest extends BaseTest {
StoreListActivity storeListActivity;
StoreModel storeModel;
UserModel userModel;
@Before
public void setUp() throws Exception {
storeListActivity = Robolectric.buildActivity(StoreListActivity.class).get();
storeModel = new StoreModel(storeListActivity.getApplicationContext());
userModel = new UserModel(storeListActivity.getApplicationContext());
}
@Test
public void activityExists() {
assertThat(storeListActivity).isNotNull();
}
@Test
public void fetchAllStoresWhenWifiIsOn() {
ConnectivityManager cm =(ConnectivityManager)Robolectric.application.getSystemService(Context.CONNECTIVITY_SERVICE);
Robolectric.shadowOf(cm).setNetworkInfo(ConnectivityManager.TYPE_WIFI, cm.getActiveNetworkInfo());
boolean result = storeModel.fetchAllStores();
assertTrue(result);
}
storeModel.fetchAllStores() implementation has this ugly cast:
MyModel myModel = ((MyApplication) context.getApplicationContext()).getMyModel;
So is there a way for testing with Robolectric portion of code that contains cast like this ?
((MyApplication) context.getApplicationContext())
Upvotes: 4
Views: 4766
Reputation: 8142
Encountered the same error;
java.lang.ClassCastException: androidx.test.runner.AndroidJUnitRunner cannot be cast to org.robolectric.android.fakes.RoboMonitoringInstrumentation
I realized I was using the wrong implementation for Roboelectric:
implementation "org.robolectric:robolectric:4.5.1"
If you are using this please replace it with testImplementation instead:
testImplementation "org.robolectric:robolectric:$robolectricVersion"
Upvotes: 0
Reputation: 462
You may need to specify the path to your AndroidManifest.xml for your test. You can do so using as follows:
@Config(manifest = "/path/to/your/AndroidManifest.xml")
@RunWith(RoboletricTestRunner.class)
public class StoreFinderTest extends BaseTest {
...
}
You can make Robolectric use a test version of your application by simply creating a TestMyApplication class (i.e. class with prefix "Test" before the name of your application class) in the same package as your MyApplication in the test directory of your project. To work around your casting problem, TestMyApplication should extend MyApplication:
public class TestMyApplication extends MyApplication {
}
Upvotes: 5
Reputation: 72
I don't know Robolectric but maybe add an
if(context.getApplicationContext() instanceof MyApplication
statement
Upvotes: -3