简体   繁体   中英

How to spy on Activity when using Robolectric

I am new on Android and I am playing around with Robolectric for my unit tests. I am facing the following problem.

I have an activity I want to test.

MainActivity.java

public class MainActivity extends ActionBarActivity
        implements NavigationDrawerFragment.NavigationDrawerCallbacks {

    private NavigationDrawerFragment mNavigationDrawerFragment;

    @Override
    protected void onCreate (Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mNavigationDrawerFragment = (NavigationDrawerFragment)
                getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);

        mNavigationDrawerFragment.setUp(
                R.id.navigation_drawer,
                (DrawerLayout) findViewById(R.id.drawer_layout));
    }

    @Override
    public void onNavigationDrawerItemSelected (int position) {
        ...
    }
}

This is the test class:

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class MainActivityTests {

    private ActivityController<MainActivity> controller;
    private MainActivity activity;
    private MainActivity spy;

    @Test
    public void onCreate_shouldStartNavigationDrawerFragment () {

        controller = Robolectric.buildActivity(MainActivity.class);
        activity = controller.get();
        assertThat(activity).isNotNull();

        spy = spy(activity);
        spy.onCreate(null);

        verify(spy).onCreate(null);
    }
}

But I am getting the following exception:

java.lang.IllegalStateException: System services not available to Activities before onCreate() at line spy.onCreate(null) .

I have been googling for hours and I have tried several workarounds (blindly) without any success. May please anyone guide me?

Here's what did the trick for me. I use attach() before getting an activity to spy on. Tested with Robolectric 3.0

private MainActivity spyActivity;

@Before
public void setUp(){

    MainActivity activity = Robolectric.buildActivity(MainActivity.class).attach().get();
    spyActivity = spy(activity);

    spyActivity.onCreate(null);

}

You should be driving the activity lifecycle through Robolectric. See: http://robolectric.org/activity-lifecycle/

So for your case you could do:

controller = Robolectric.buildActivity(MainActivity.class);
activity = controller.get();
assertThat(activity).isNotNull();
spy = spy(activity);
controller.create();

Note: it usually doesn't make sense to spy on the activity lifecycle when testing with Robolectric, since you're the one driving it, so you're only testing that your own method calls executed.

It means that you have to first call the onCreate() method. It has to be the very first called method.

If interested in using exactly the same controller, and work with a spy of the activity, you could modify the inner class of the controller via Reflection, check this method:

public static <T extends Activity> T getSpy(ActivityController<T> activityController) {
    T spy = spy(activityController.get());
    ReflectionHelpers.setField(activityController, "component", spy);
    return spy;
}

The ReflectionHelper is available in Robolectric (tested on Robolectric 4.2). Then it is initialized like this:

controller = Robolectric.buildActivity(MainActivity.class);
activity = getSpy(controller.get());

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM