10

Android アプリの単体テストを作成しようとしていますが、mockito でやりたいことがうまくいきません。これは Robolectric と組み合わせて使用​​されており、私は問題なく動作しており、単体テストが機能することを実証しています。

Bluetooth デバイスが接続されているかどうかに応じて、ボタンが新しいアクティビティを開くかどうかをテストしたいと思います。明らかに、私のテストでは Bluetooth に接続されたデバイスはありませんが、あたかも存在するふりをしたいと思います。Bluetooth 接続の状態は Application クラスに保存されます。この値を変更するための公的にアクセス可能な方法はありません。

したがって、基本的にアプリのロジックは次のようになります。

HomeActivity.java:

//this gets called when the button to open the list is clicked.
public void openListActivity(View button) { 
  MyApplication myApplication = (MyApplication) getApplication();
  if (myApplication.isDeviceConnected() {
      startActivity(new intent(this, ListActivity.class));
   }
}

これをテストするために、次のことを行いました。

TestHomeActivity.java:

@Test
public void buttonShouldOpenListIfConnected() {
    FlexApplication mockedApp = Mockito.mock(MyApplication.class);
    Mockito.when(mockedApp.isDeviceConnected()).thenReturn(true);
    //listViewButton was setup in @Before
    listViewButton.performClick();
    ShadowActivity shadowActivity = Robolectric.shadowOf(activity);

    Intent intent = shadowActivity.getNextStartedActivity();
    assertNotNull(intent); //this fails because no new activity was opened. I debugged this and found that isDeviceConnected returned false.
    ShadowIntent shadowIntent = Robolectric.shadowOf(intent);
    assertThat(shadowIntent.getComponent().getClassName(), equalTo(ListActivity.class.getName()));
}

したがって、モック フレームワークで true を返すように指示したと思っていたにもかかわらず、(アクティビティ内で) isDeviceConnected への呼び出しが false を返すため、単体テストは失敗します。ただし、テストでこのメソッドがtrueを返すようにしたいです。これはmockitoの機能ではありませんか、それともmockitoの使い方を完全に間違えていますか?

4

2 に答える 2

6

それがmockitoの仕組みですが、問題は次のとおりlistViewButtonですmockedApp。テストメソッドで作成mockedAppしていて、どこにも設定していないため、そうではないようです。Mockito は、 のすべてのインスタンスのメソッド呼び出しをモックするのではなくApplication、モックとして宣言したものからのみモックします。

私は個人的にアンドロイドがApplicationクラスでどのように機能するかわかりませんが、どこかに設定する必要があるので、listViewmockedAppは通常受け取るものの代わりにあなたのものを使用します。

編集getApplication更新された質問の後、保護されたメソッドでspyあなた を変換し、listViewButtonそれを返すようにすることができますmockedApp. それは少し悪いにおいがしますが、アプリケーションのモック オブジェクトを に設定できない場合の 1 つの方法ですlistViewButton

EDIT2

読みやすさのために使用するテストでスパイを使用する例BDDMockito:)

public HomeActivity {
    ...
    protected MyApplication getApplication() {
       // real code
    }
    ...
}

public void TestHomeActivity {
   private HomeActivity homeActivity;

   @Before
   public void setUp() {
       this.homeActivity = spy(new HomeActivity());
   }

   @Test
   public void buttonShouldOpenListIfConnected() {
       // given
       FlexApplication mockedApp = Mockito.mock(MyApplication.class);
       Mockito.when(mockedApp.isDeviceConnected()).thenReturn(true);
       // IMPORTANT PART
       given(homeActivity.getApplication()).willReturn(mockedApp);
       ...
   }
}

その後、テストは期待どおりに機能するはずです。しかし、私は強調します:内部に HomeActivityspyを注入できない場合にのみ使用してください。mockedApp

于 2012-12-20T21:06:32.177 に答える