情報は力ではない

VimとかC++とかCUDAとか。

ActivityUnitTestCaseでIllegalStateException

Androidのテストを学ぶためにCreating Unit Tests | Android Developersを読みながら、そのサイトに載っているAndroidTestFunを写経していた。その時、ちょっと詰まってしまったのでメモ。

ActivityUnitTestCaseのstartActivity()を起点にした例外

AndroidTestFunプロジェクトのlesson4にLaunchActivityTestクラスがあるのだけれど、そのtestPreconditions()を書いてテストを走らせた時に例外が発生した。testPrecondisions()のコードは次のようなもの。

   @MediumTest
    public void testPreconditions() {
        //Start the activity under test in isolation, without values for savedInstanceState and
        //lastNonConfigurationInstance
        startActivity(mLaunchIntent, null, null);
        final Button launchNextButton = (Button) getActivity().findViewById(R.id.launch_next_activity_button);

        assertNotNull("mLaunchActivity is null", getActivity());
        assertNotNull("mLaunchNextButton is null", launchNextButton);
    }

テストのログを見てみると次のようなエラーメッセージが書いてあった。

java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

なぜこんな例外が発生するのだろうと思って少し調べてみると、こんなサイトがあった。
Issue 128421 - android - ActivityUnitTestCase startActivity() IllegalStateException - Android Open Source Project - Issue Tracker - Google Project Hosting
どうやら同じような例外が発生している人がいるみたいだった。
このissueでは2つの解決法が提供されていた。

  1. setActivity()をオーバーライドする方法
  2. contextを明示的に設定する方法

setActivity()をオーバーライドする方法

@Override
    protected void setActivity(Activity testActivity) {
        if (testActivity != null) testActivity.setTheme(R.style.AppTheme);
        super.setActivity(testActivity);
    }

contextを明示的に設定する方法

protected void setUp() throws Exception {
   super.setUp();
      
   ContextThemeWrapper context = new ContextThemeWrapper(
          getInstrumentation().getTargetContext(), R.style.AppTheme);
   
   setActivityContext(context);

   (...)
}

自分の場合、どちらの方法を使っても例外が発生しなくなった。
原因はよくわかっていないけど、とりあえずこれでまた写経を始めることができる。