Robolectric和Mockito监视Android活动

时间:2015-01-05 20:16:50

标签: java android testing mockito robolectric

这是我的第二个问题,与Robolectric + Mockito有关。我一直在努力解决这个问题。我想要做的是窥探一个Activity来测试它的onCreate()回调方法。

我不知道如何在其生命周期中驱动间谍活动以调用onCreate()。这是我的活动:

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();
    }

}

这是我尝试测试它:

@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);

    }
}

但是,当测试调用spy.onCreate(null)时,我得到以下异常:

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)

当然,如果我不调用它,Verify()会失败,因为onCreate没有被执行。那么,这是正确的方法吗?如何使用Activity监视Mockito并在其生命周期中推动它?

3 个答案:

答案 0 :(得分:2)

可能有两种解决方案。

一:

setup()方法中,替换controller = Robolectric.buildActivity(MainActivity.class).attach();而不是controller = Robolectric.buildActivity(MainActivity.class);

另一个:

首先,你应该正确监视活动。 请参阅我在another post

中使用robolectric监视活动的答案

其次,请勿直接针对间谍活动致电onCreate(),您应致电ActivityController create(),在您的情况下,请致电controller.create()而不是{ {1}}

答案 1 :(得分:0)

使用Robolectric,您必须致电controller.create();开始活动。之后它应该工作。

答案 2 :(得分:0)

你需要在get()之前调用setup():

controller.setup();

如果不需要控制器实例,我强烈建议您通过以下代码获取Activity:

activity = Roblectric.setupActivity(MainActivity.class);

正如我们所看到的,这些API之间的区别是setup()然后是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();
  }

因此崩溃的原因是setup():

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

它是一个模拟生命周期,不是吗?

最后希望这有助于你和其他人也需要它。