lundi 5 janvier 2015

Robolectric and Mockito spying Android Activity

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


I don't know how to drive the 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 call it, the Verify() fails because onCreate is no executed. So, Is this the right way to do it? how could spy an Activity using Mockito and drive it through its lifecycle?


Aucun commentaire:

Enregistrer un commentaire