20

私はrobolectricを使用して、Androidユニットテストを十分に高速にして便利にしています。私が書いたコードが、一般的な実際のユースケースをシミュレートするために画面の向きが変化している間に機能することをテストしたいと思います。

具体的には、私がテストしているのは、結果がフェッチされた後にいくつかのxmlが解析されるサーバーへの非同期http呼び出しです。うまく機能しているすべての単体テストがありますが、画面の回転をシミュレートする方法がわかりません。アクティビティがそれ自体を再作成する原因となる状態の変化は問題ありません。必ずしも画面の回転である必要はありません。

テストを1分間に数回実行し、2秒未満で実行する必要があるため、エミュレーターを使用するソリューションはオプションではありません。可能であれば、これもroboguiceで動作させたいと思います。

ありがとう。

4

4 に答える 4

19

Robolectricでrecreateを呼び出すと(Robolectricを使用するときに古いAPIバージョンについて心配する必要がないことに注意してください)、構成変更のシミュレーションにかなり近いですが、発生する可能性のあるすべてのエラーを必ずしもキャッチできるわけではありません。特に、アクティビティの新しいインスタンスは作成されません(そして、それを「スクラブ」しないと確信しています)。したがって、アクティビティのメンバーフィールドを復元するのを忘れた場合、テストはそれをキャッチしません。ただし、フラグメントのテストには十分に機能します(保持されていないフラグメントは破棄され、再インスタンス化されます)。

Robolectricテストのアクティビティでrecreateを呼び出すと、次のようになります。

  1. onSaveInstanceState
  2. onPause
  3. onStop
  4. onDestroy
  5. onCreate
  6. onStart
  7. onRestoreInstanceState
  8. onResume

(これは、テストアクティビティのほとんどのライフサイクルメソッドをオーバーライドし、ログステートメントをそれらに配置することでわかりました)

次のようなコードを使用すると、実際の構成変更に少し近づくことができます。

Bundle bundle = new Bundle();
activityController.saveInstanceState(bundle).pause().stop().destroy();
controller = Robolectric.buildActivity(YourActivity.class).create(bundle).start().restoreInstanceState(bundle).resume();
activity = controller.get();

(このコードはRobolectric 2.1用です-2.2以上を使用している場合は、.visible()その後に電話をかける必要があります.resume()

上記を使用すると、次のイベントが発生することがわかります。

  1. onSaveInstanceState
  2. onPause
  3. onStop
  4. onDestroy
  5. インスタンス化されたアクティビティの新しいインスタンス(以降のすべての呼び出しはこの新しいインスタンスで行われます)
  6. onCreate
  7. onStart
  8. onRestoreInstanceState
  9. onResume
  10. onPostResume

これはまだ完全に一致しているわけではありませんが、実際の構成変更が発生したときに発生することにはるかに近いものです。

これは、recreate()の呼び出しとは異なり、メモリ不足のためにアクティビティが破棄されたときに何が起こるかについての適切なシミュレーションであると思います。これにより、保持されたフラグメントへの参照が保持されるとは思いません。私はこの地域で不安定な地面にいます!

アップデート:

アクティビティがインテントを介して開始された場合は、次のようにwithIntentへの呼び出しを追加する必要があります。

Robolectric.buildActivity(YourActivity.class).withIntent(intent).create(bundle) // and so on...
于 2014-02-17T18:33:46.073 に答える
10

コンパイルしているAndroidAPIレベルは何ですか?3.0以上の場合は、試してみてくださいActivity.recreate()。ドキュメントには次のように記載されています。

このアクティビティを新しいインスタンスで再作成します。これにより、構成の変更によりアクティビティが作成されたときと基本的に同じフローになります。現在のインスタンスはそのライフサイクルを経てonDestroy()になり、その後に新しいインスタンスが作成されます。

でも自分で試したことはありません。

于 2011-07-19T21:24:06.950 に答える
10

ZoFreXの回答を使用して成功しましたが、実際に回転をシミュレートする方法を追加したいと思います。OPがローテーションは絶対に必要ではないと指定したことは知っていますが、タイトルはこれを回答に含める必要があることを示唆しており、ここで迷子になってしまう人々を助けることができます。

基本的に、ZoFrexのソリューションを適用する前に、アクティビティの方向を設定します。またはより簡潔にコードで:

// toggle orientation
int currentOrientation = fragment.getActivity().getResources().getConfiguration().orientation;
boolean isPortraitOrUndefined = currentOrientation == Configuration.ORIENTATION_PORTRAIT || currentOrientation == Configuration.ORIENTATION_UNDEFINED;
int toOrientation = isPortraitOrUndefined ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
Robolectric.application.getResources().getConfiguration().orientation = toOrientation;

// ZoFreX's solution
Bundle bundle = new Bundle();
activityController.saveInstanceState(bundle).pause().stop().destroy();
controller = Robolectric.buildActivity(YourActivity.class).create(bundle).start().restoreInstanceState(bundle).resume();
activity = controller.get();

ここに含まれていない追加情報が含まれているため、ZoFreXのソリューションを確認してください。

于 2014-10-20T14:38:43.553 に答える
4

RobolectricのActivityControllerクラスには、おそらくこれを処理するconfigurationChange()メソッドがあります。地獄、それもjavadocコメントがあります!:D

于 2017-01-08T17:23:06.317 に答える