Robolectric and Mockito Activity for Android

This second question of mine is related to Robolectric + Mockito. I've been struggling with this for a couple of days. What I'm trying to do is test the action to test its onCreate () callback method.

I dont know how to manage a spied Activity through its lifecycle in order to call onCreate (). This is my activity:

public class MainActivity extends FragmentActivity {

    public Session session; // Facebook session

    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        session = getActiveSession();
        if (session == null ) {
            // ...
        } else {
            if (sessionClosed()) {
                LoginFragment fragment = new LoginFragment();
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.container, fragment);
                ft.commit();
            }
        }
    }

    ...

    public Session getActiveSession() {
        return Session.getActiveSession();
    }

    public boolean sessionClosed() {
        return session.isClosed();
    }

}

      

And this is my attempt to test it:

@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {

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

    @Before
    public void setup() throws Exception {
        controller = Robolectric.buildActivity(MainActivity.class);
        activity = (MainActivity) controller.get();
    }

    ...

    @Test
    public void testShowLoginWhenSessionClosed() throws Exception {
        Session session = new Session(Robolectric.application);
        spy = Mockito.spy(activity);

        Mockito.doReturn(session).when(spy).getActiveSession();
        Mockito.doReturn(true).when(spy).sessionClosed();

        spy.onCreate(null);

        Mockito.verify(spy).getActiveSession();

        Fragment fragment = 
            spy.getSupportFragmentManager().findFragmentById(R.id.container);
        Assert.assertTrue(fragment instanceof LoginFragment);

    }
}

      

However, when the test calls spy.onCreate(null)

, I get the following exception:

java.lang.IllegalStateException: System services not available to Activities before onCreate()
at android.app.Activity.getSystemService(Activity.java:4492)
at android.view.LayoutInflater.from(LayoutInflater.java:211)
at org.robolectric.shadows.ShadowActivity.getLayoutInflater(ShadowActivity.java:148)
at android.app.Activity.getLayoutInflater(Activity.java)
at org.example.MainActivityTest.testShowLoginWhenSessionClosed(MainActivityTest.java:110)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
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)

      

And of course, if I don't name it, it Verify()

fails because it onCreate

fails. So, is this the correct way to do it? How can you use Activity

using Mockito

and manage it through your life cycle?

+3


source to share


3 answers


There are two possible solutions.

One:

B setup()

, replace controller = Robolectric.buildActivity(MainActivity.class).attach();

insteadcontroller = Robolectric.buildActivity(MainActivity.class);




Other:

First, you must follow the action correctly. See my answer for tracking activity with robolectric

in another post

Secondly, don't call onCreate()

directly on the spied activity, you should call ActivityController

create()

, in your case call controller.create()

insteadspy.onCreate(null);

+1


source


With Robolectric, you have to call controller.create();

to start your activity. After that, it should work.



0


source


You just need to set up connection () before get ():

controller.setup();

      

And if the controller instance is redundant, I highly recommend that you get the action by the following code:

activity = Roblectric.setupActivity(MainActivity.class);

      

As we can see, the difference between these APIs is setup () and then get ():

  public static <T extends Activity> ActivityController<T> buildActivity(Class<T> activityClass) {
    return ActivityController.of(shadowsAdapter, activityClass);
  }

  public static <T extends Activity> T setupActivity(Class<T> activityClass) {
    return ActivityController.of(shadowsAdapter, activityClass).setup().get();
  }

      

So, the reason for your failure is setup ():

  public ActivityController<T> setup() {
    return create().start().postCreate(null).resume().visible();
  }

      

this is a lifecycle mock, right?

Finally, I hope you and someone else will need this help.

0


source







All Articles