あなたの質問に対する簡単な回答は、Robolectric が Android クラスを JVM で実行されるコードに変換する方法が原因で、多くの機能が期待どおりに動作しないということです。多くのシステム コールバックは実行されず、クラスの Shadow 実装で Robolectric が提供するものに依存する必要があります。(@Steven_BDawg が提供するリンクを参照してください)。
長い答え: このフロー全体を 1 つの大きなテストで実装することは可能かもしれませんが、それはフレームワークの設計目的ではありません。
一般に、Robolectric と単体テストは、あなたが説明した方法で使用することを意図したものではありません。 ウィキペディアのユニット テストのページには、ユニットをアプリケーションのテスト可能な最小部分と見なすことができると記載されています。単体テスト スイートには、多くの軽量テストを含める必要があります。各テストでは、アプリの機能の一部を分離し、適切に動作していることを確認します。
A と B の 2 つのアクティビティを含む基本的なアプリケーションを考えてみましょう。アクティビティ A はトピックに関する情報を表示し、アクティビティ B はユーザーが A に表示するトピックを選択できるようにします。ユーザーがアクティビティ A からアクティビティ B に移動すると、B は取得します。で呼び出されstartActivityForResult()
、選択したトピックで A に戻る必要があります。
ここで、A が B から結果を取得してデータを表示するこのフローを単体テストしたいとします。これを 2 つのテストに分割できます。
- テスト中のアクティビティ - アクティビティ A. このテストでは、アクティビティ A の新しいインスタンスを作成します。Robolectric テストでは、B が A に戻ることを期待するインテントを作成し、A のシャドウ メソッド
receiveResult()
を呼び出して、 OK の結果コードとこの Intent を持つ引数。の後receiveResult()
、アサーションを実行します。アクティビティ A が結果を適切に処理することがわかりました。
- テスト中のアクティビティ - アクティビティ B。このテストでは、アクティビティ B の新しいインスタンスを作成し、アクティビティ A からの結果に対して開始されたかのように設定します。Robolectric テストでは、選択に必要なすべてのアクションを実行します。データを送信し、送り返すインテントを作成し、そのインテントに対してアサーションを実行して、それが正しく作成されたことを確認します。
これは非常に簡単な例です。この 2 つのステップは、さらに多くのテストに分割される可能性があります。繰り返しますが、各単体テストは、アプリを分割できる機能の最小単位のみをテストする必要があるためです。この例は主に、単体テストのような方法で考え始めるのに役立ちます。単体テストの理解が深まるにつれて、コードの書き方が変わってきたことがわかりました。私は、メソッドやクラスがあまりにも多くの作業を行い、適切に単体テストできないような方法で記述しないようにしています。経験則として、単体テストが容易なコードは、コードを初めて読んだときにすぐにわかる非常に具体的な操作を実行します。
最後に、これをさらに一歩進めたい場合は、フレームワークのモックを使用すると、単体テストを行う能力が大幅に向上します。 Mockitoは、私が過去に成功したモッキング フレームワークです。モッキング フレームワークの目的は、動作を厳密に制御するスタブ オブジェクトを作成することです。Mockito (またはその他のモッキング フレームワーク) を使用すると、必要な任意の型から拡張されたオブジェクトを定義し、必要なメソッドのみを実装できます。これらのメソッド呼び出しに対する応答を直接制御できます。これは単体テストに役立ちます。必要なオブジェクトは、テスト対象のオブジェクトです。他のすべてのオブジェクトをモックすることにより、テスト対象のオブジェクトが適切に動作しているかどうかをよりよく理解できます。これは、他のすべての動作がテスト担当者によって明示的に定義されているためです。(もちろん、これは多くの余分なコードにつながりますが、それは優れた単体テスト担当者の人生です。ただし、前述のように、単体テストに慣れるにつれて、モックやコードの作成をあまり必要としないメソッドを記述していることに気付くかもしれません。一部のコーダーは、コードをタイトに保ち、単一の目的に集中するために、コーディングする前に単体テストを作成することさえあります)
お役に立てれば!