Adding intent to activity in Robolectric before onCreate

2.1k views Asked by At

I'm trying to create an intent with extras for an activity whilst running under Robolectric. Because of the way we are using dependency injection, I need to call an Activity default constructor prior to calling the onCreate method. This is so I can set up some mocks on our injected variables prior to onCreate.

My objective is to create an Activity object, perform some initialisation on fields held in the activity, then invoke the activity lifecycle methods to include an intent with an extra data bundle.

The standard approach for creating and starting an activity with Robolectric would be something like this:

        Robolectric.buildActivity(Activity.class)
            .withIntent(intent)
            .create()
            .visible()
            .start()
            .resume()
            .get();

I was attempting to split the calls in two, so I create the ActivityController and the get the Activity from it. Once my pre onCreate initialisation is complete I then use the ActivityController to invoke the Activity lifecycle methods like this:

ActivityController controller = Robolectric.buildActivity(Activity.class);
Activity activity = ac.get();

/* Do some activity related initialisation */

controller
  .withIntent(intent)
  .create()
  .visible()
  .start()
  .resume()
  .get();

Unfortunately, that won't compile because the compiler objects to .create() following .withIntent(intent), even though it's perfectly happy to chain the calls directly behind Roboectric.buildActivity which returns the ActivityController.

I tried moving the withIntent(intent) as shown below

ActivityController controller = Robolectric.buildActivity(Activity.class)
                                           .withIntent(intent);
Activity activity = ac.get();

/* Do some activity related initialisation */

controller
  .create()
  .visible()
  .start()
  .resume()
  .get();

Everything seemed to work OK, but then the intent in the created activity seems to lose the extra bundle. Any suggestions on how to achieve my objective would be gratefully received

PS I know that calling a default constructor in Activity is something you would never do in an app, but this is just for unit testing.

1

There are 1 answers

0
drew On

I eventually discovered my error. I had not declared my methods with the correct generic typing. The following method declarations compile correctly and the intent data is passed to the activity in its lifecycle methods.

public static  ActivityController createActivityController(Class clazz) {
    return Robolectric.buildActivity(clazz);
}


public static <T extends FragmentActivity> void startControllerActivity(ActivityController<T> activityController, Intent intent) {
    activityController
            .withIntent(intent)
            .create()
            .visible()
            .start()
            .resume();
}

So the unit test set up would look something like this...

ActivityController<MyActivity> activityController = createActivityController(MyActivity.class);
MyActivity activity = activityController.get();
activity.setSomeProperty(1);
Intent intent = new Intent();
intent = new Intent(Robolectric.application.getApplicationContext(), MyActivity.class);
intent.putExtra(EXTRA_KEY, "Extra value");
startControllerActivity(activityController, intent);