Robolectric — その概要、動作原理、Android単体テスト

著者: IT Sectr 公開日: 2026-04-09 読了時間: 8 分

Robolectricは、エミュレーターや実機を使用せずにJVM上で直接テストを実行できるAndroidアプリケーション用の単体テストフレームワークです。Android SDKの呼び出しをインターセプトし、実際のコンポーネントの動作をエミュレートするシャドウオブジェクトを提供します。Robolectric Documentation, 2025によると、シャドウオブジェクトは約1万5千のAndroid APIクラスを置き換え、プラットフォームからテストを分離します。

重要ポイント

  • Robolectric — エミュレーター不要でJVM上で動作するAndroid単体テストフレームワーク
  • シャドウオブジェクトがAndroid SDKの呼び出しをインターセプトし、システム動作をエミュレート
  • JUnit 4および5との統合により標準テストランナーを使用可能
  • テストはエミュレーターのような分数ではなく、秒単位で実行
  • 対応 Jetpack Compose、フラグメント、インテント、ContentProvider、リソース

Robolectricとは

Robolectricは、2010年にAndroidアプリケーションテストを高速化するために作成されたオープンソースフレームワークです。エミュレーターやデバイス上で実行する代わりに、RobolectricはAndroid SDKクラスのシャドウ実装を提供し、Java仮想マシン(JVM)上で直接動作します。これにより、数千のテストを秒単位で実行できます。

Robolectricが解決する問題

従来のAndroidテストでは、エミュレーター上でアプリケーションを実行する必要があり、APKのビルド、インストール、起動に3〜10分かかります。Robolectricはこのステップを排除します。テストは通常のJava/Kotlinテストとしてコンパイルされ、JUnitを介して実行されます。これにより、分数ではなく秒単位のフィードバックループが実現します。

サポートされるAndroidバージョン

RobolectricはAPI 16(Android 4.1)から最新の安定版リリースまでのすべてのAndroidバージョンをサポートします。各バージョンに対して、アプリケーションがテストされているプラットフォームバージョンの動作をエミュレートする対応するシャドウオブジェクトのセットが提供されます。

アーキテクチャとシャドウオブジェクト

Robolectricのアーキテクチャは、クラスローダーの置き換えによる呼び出しのインターセプトメカニズムに基づいています。テストがAndroid SDKのメソッドを呼び出すと、Robolectricがその呼び出しをインターセプトしてシャドウオブジェクトに転送します。シャドウオブジェクトは、Androidコンポーネントの実際の動作を模倣するJavaクラスですが、ネイティブプラットフォームなしで動作します。

シャドウの仕組み

シャドウオブジェクトは、元のAndroidクラスの主要メソッドを実装します。例えば、ShadowTextViewはgetText()、setText()、getCurrentTextColor()などのメソッドを模倣します。textView.setText("こんにちは")が呼び出されると、シャドウが文字列を保存し、getText()が呼び出されたときにそれを返します。これにより、テストを実際のレンダリングやシステムサービスから分離します。

シャドウの階層

Robolectricは、Android SDKの主要コンポーネント(Activity、Fragment、TextView、Button、RecyclerView、WebView、LocationManager、ConnectivityManagerなど)をカバーする200以上のシャドウクラスをサポートしています。シャドウオブジェクトは、元のAndroidクラスと同じ継承階層に従います。

Robolectricのインストールと設定

GradleプロジェクトにRobolectricをインストールするには、依存関係testImplementation "org.robolectric:robolectric:4.x"を追加する必要があります。また、build.gradleファイルでandroidsdk設定を指定し、android:testInstrumentationRunnerを追加する必要があります。Robolectricを使用するためにAndroidテストプラグインは必要ありません。

基本的なGradle設定

依存関係を追加した後、マニフェスト、リソース、アセットのディレクトリを設定する必要があります。Robolectricは自動的にAndroidManifest.xmlを見つけますが、@Configアノテーションやシステムプロパティを使用してパスを手動で指定する必要がある場合があります。マルチモジュールプロジェクトの場合、設定はモジュールごとに個別に設定されます。

groovy
// build.gradle — Robolectricの設定
android {
    testOptions {
        unitTests.includeAndroidResources = true
        unitTests.all {
            systemProperty 'robolectric.dependency.dir',
                project.rootDir.absolutePath + '/build/intermediates'
        }
    }
}

dependencies {
    testImplementation 'org.robolectric:robolectric:4.13'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

@Configアノテーション

@Configアノテーションを使用すると、テストパラメーター(sdk:APIバージョン、manifest:マニフェストへのパス、qualifiers:画面設定、言語)を上書きできます。これは、異なるAndroidバージョン、画面の向き、ローカライゼーションでのアプリケーションの動作をテストするのに便利です。

Robolectricを使ったテスト作成

Robolectricテストは、JUnit 4の場合は@RunWith(RobolectricTestRunner.class)、JUnit 5の場合はRobolectricExtensionを使用して通常の単体テストとして作成されます。ActivityControllerはActivityのライフサイクル(create()、start()、resume()、pause()、stop()、destroy())を管理します。これにより、各状態遷移を詳細にテストできます。

Activityのテスト

Activityをテストするには、ActivityControllerを使用し、ライフサイクルステージを順に通過します。Activityへのアクセスはcontroller.get()を介して行います。すべてのビューコンポーネントは、実際のアプリケーションと同様にfindViewByIdを介してアクセスできます。シャドウオブジェクトを使用すると、テキスト、可視性、色、その他のビュー属性を確認できます。

java
@RunWith(RobolectricTestRunner.class)
@Config(sdk = BuildConfig.SDK_INT)
public class MainActivityTest {

    @Test
    public void testActivityDisplaysGreeting() {
        ActivityController<MainActivity> controller =
            Robolectric.buildActivity(MainActivity.class);
        controller.create().start().resume();

        MainActivity activity = controller.get();
        TextView greeting = activity.findViewById(R.id.greeting);
        ShadowTextView shadow = Shadows.shadowOf(greeting);

        assertEquals("Welcome!", shadow.getText());
    }
}

インテントとナビゲーションのテスト

RobolectricはstartActivity()呼び出しをインターセプトし、ShadowActivityを介して送信されたインテントを確認できます。これにより、ボタンをクリックしたときに正しいAction、Data、Extraパラメーターを持つIntentが送信されるかを検証するなど、ナビゲーションのテストが可能になります。

java
@Test
public void testNavigationToDetails() {
    controller.create().start().resume();
    MainActivity activity = controller.get();

    activity.findViewById(R.id.detailsButton).performClick();

    ShadowActivity shadowActivity = Shadows.shadowOf(activity);
    Intent intent = shadowActivity.getNextStartedActivity();
    assertEquals(
        DetailsActivity.class.getName(),
        intent.getComponent().getClassName()
    );
}

Robolectric vs エミュレーター

Robolectricとエミュレーターは異なるタスクを解決します。Robolectricは高速な単体テスト、UIロジック、ビジネスコンポーネント、リポジトリの検証に最適です。エミュレーターはインストルメンテーションテスト、APIとの統合検証、カメラ、センサー、パフォーマンスのテストに必要です。

特性Robolectricエミュレーター
速度100テストあたり約5秒100テストあたり約5分
起動APKビルド不要APKビルドが必要
リアルAPIシャドウエミュレーションネイティブAndroid SDK
標準機能JUnitのみ任意のフレームワーク

ViewModelとRepositoryのテスト

Robolectricは、Android SDKを使用するが実際のUIを必要としないコンポーネント(ViewModel、Repository、UseCase)のテストに最適です。ViewModelはRobolectricExtensionを使用した通常のJUnitテストを介してテストされ、ライフサイクルコンポーネント(LiveData、StateFlow)はモックなしでシャドウ環境で動作します。

LiveDataのテスト

RobolectricはLiveDataを標準でサポートしています。テスト内でLiveDataを購読し、ViewModelを介して状態を変更し、発行された値を確認できます。非同期操作には、InstantTaskExecutorRuleまたはコルーチン用のrunBlockingを使用します。これにより、アーキテクチャコンポーネントをモックする必要がなくなります。

kotlin
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [BuildConfig.SDK_INT])
class ProfileViewModelTest {

    private val repository = FakeUserRepository()
    private val viewModel = ProfileViewModel(repository)

    @Test
    fun `loading profile sets state to success`() = runBlocking {
        viewModel.loadProfile("user123")
        val state = viewModel.profileState.getOrAwaitValue()
        Assertions.assertTrue(state is UiState.Success)
    }
}

カスタムシャドウオブジェクト

標準のRobolectricシャドウオブジェクトが必要なAndroid SDKクラスをカバーしない場合は、カスタムシャドウを作成できます。これを行うには、@Implements(ClassName.class)アノテーションを持つクラスを作成し、@Implementationで必要なメソッドを実装します。カスタムシャドウは@Config(shadows = [CustomShadow::class])を介して登録されます。

ContentProviderとリソースのテスト

RobolectricはRobolectric.buildContentProvider()を介したContentProviderのテストをサポートしています。CRUD操作、URIマッチングによるクエリ、アクセス権限の処理を確認できます。リソース(文字列、色、寸法)はRuntimeEnvironment.application.resourcesを介してもアクセス可能で、リソースに依存するコードのテストが可能です。

エミュレーターからRobolectricへの移行

インストルメンテーションテストからRobolectricへの移行には、アプローチの変更が必要です。インストルメンテーションテスト(AndroidJUnit4)はエミュレーター上で実際の動作を検証しますが、Robolectricはシャドウ環境で分離されたロジックを検証します。ビジネスロジックはRobolectricテストでカバーし、インストルメンテーションテストは統合シナリオ用に残すことを推奨します。

既存テストの適応

移行時には、AndroidJUnit4をRobolectricTestRunnerに置き換え、ターゲットSDKバージョンで@Configを追加し、ActivityTestRuleをActivityControllerに置き換え、依存関係をandroidTestImplementationからtestImplementationに移動します。モック(MockK、Mockito)は変更なしでRobolectricで動作します。これらはプラットフォームに依存しません。

移行の制限

Robolectricは以下をサポートしていません:カメラ(CameraX)、NFC、Bluetooth、生体認証、実際のファイルやネイティブライブラリの操作。これらのシナリオにはエミュレーターでのインストルメンテーションテストが必要です。Robolectricは実際のレンダリングも再現しません。レイアウトテストはCompose Test RuleまたはEspressoを介して行うのが良いでしょう。ただし、ビジネスロジック、ナビゲーション、ViewModel状態の検証に関しては、Robolectricは10倍の高速実行でエミュレーターを完全に置き換えます。

JavaおよびKotlinバージョンとの互換性

RobolectricにはJDK 11以上が必要で、AGP(Android Gradle Plugin)7.0から最新の安定版まで互換性があります。RobolectricのSDKマネージャーは、初回実行時に必要なAndroid APIバージョンを自動的にダウンロードします(一度きりの操作です)。CIサーバーの場合は、初回テスト実行時の遅延を避けるために、sdkmanagerを介してSDKを事前にロードすることを推奨します。Robolectricを新しいバージョンに更新する場合、通常はテストコードの変更は必要なく、build.gradleの依存関係番号を更新するだけです。

MockKおよびMockitoとの統合

Robolectricは人気のあるモッキングフレームワークと互換性があります:Kotlin用のMockKとJava用のMockitoです。モックは依存関係(リポジトリ、APIクライアント、SharedPreferences)を分離するために使用されます。重要なルールは、Android SDKクラスをモックしないことです。そのためにはシャドウオブジェクトがあります。アプリケーション層(UseCase、Repository、DataSource、その他のビジネスロジックコンポーネント)のみをモックしてください。シャドウオブジェクトとモックのこの組み合わせにより、最小限のテスト作成労力で最大の柔軟性が得られます。

よくある質問

RobolectricとEspressoの違いは何ですか?

Espressoはエミュレーターまたはデバイス上で実行されるインストルメンテーションフレームワークです。RobolectricはJVM上で動作する単体テストフレームワークです。Espressoは実際の動作をテストし、Robolectricはシャドウ環境で分離されたロジックをテストします。両者は相互に補完します。

Jetpack ComposeはRobolectricでテストできますか?

はい、Robolectricはバージョン4.8以降Jetpack Composeをサポートしています。Composeコンポーネントのテストは、エミュレーターと同様にComposeTestRuleを使用して実行されます。ただし、Robolectric上のComposeテストは実際のレンダリングをチェックせず、コンポジションロジックのみを検証します。

RobolectricはGradleモジュールとどのように連携しますか?

Robolectricはマルチモジュールプロジェクトをサポートしています。各モジュールは独自のマニフェストとリソースで個別に設定されます。UIコンポーネントのないモジュールの場合は、Androidプラグインなしのライブラリモジュールで十分です。数十のモジュールがある大規模プロジェクトでは、各モジュールのRobolectricテストが並行して実行され、エミュレーターでの逐次実行と比較してさらなる速度向上が得られます。

Robolectricがリソースを見つけられないのはなぜですか?

リソースの問題は、build.gradleにunitTests.includeAndroidResources = trueがない場合、またはマニフェストへの正しいパスを持つ@Configアノテーションがない場合に発生します。Robolectricはbuild/intermediatesからコンパイルされたリソースを使用します。

Robolectricテストをデバッグするには?

RobolectricテストはAndroid Studioで通常のJava/Kotlinテストと同様にデバッグできます。ブレークポイント、ステップスルーデバッグ、シャドウオブジェクトとその状態の検査が利用可能です。ロギングはVMオプションで-Drobolectric.logging=debugを設定することで有効になります。

まとめ

  • Robolectric — エミュレーター不要でJVM上で高速なAndroid単体テストを実現するフレームワーク
  • シャドウオブジェクトが200以上のAndroid SDKクラスを置き換え、その動作をエミュレート
  • ActivityおよびFragmentのライフサイクルはActivityControllerを介して状態検証とともに管理
  • インテントテストはShadowActivityを介してナビゲーションとデータ転送の検証が可能
  • JUnitおよびGradleとの統合に追加のインストルメンテーションランナーは不要
  • @ConfigアノテーションでAPIバージョン、言語、画面設定、リソースを指定
  • RobolectricとEspressoは相互補完:高速単体テストvsインストルメンテーション

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください