Mokitと仲良くなろうとしたお話
初投稿です。
皆さんは「Mockito」使っていますか?
業務でAndroid Studioを使用してアプリケーションを作成し、UnitTestを行う際にMockitoとケンカしたので、Mockitoと仲良くするため、そして自分の備忘録として投稿します。
使用環境
- macOS Catalina(10.15.6)
- Android Studio 4.0.1
- Android 9.0(sdk:28)
- Mockito Core 3.5.9
- Mockito Inline 3.5.9
- Robolectric 4.3.1
Mockitoとケンカした部分について
作成していたアプリケーションはaidlでインターフェースの提供を受けており、サービスとのbindを行うアプリケーションでした。
初めはRobolectricのShadowApplication.setComponentNameAndServiceForBindService()
を使用してMock化したIBinderを渡していましたが、IBinder.Stub.asInterface()
でインターフェースを取り出す際に別のオブジェクトになってしまうため、うまくMock化できていませんでした。
(単純に自分のMockの仕方が悪かったのかもしれないです。)
Mockito 3.4.0からstaticなメソッドもMock化できるようになったようなのですが、Webに有益な情報が見つからなかったので、以下に示します。
staticなメソッドのMock化方法
IBinder.Stub.asInterface()
など、staticなメソッドのMock化方法です。
以下のような使い方でMock化できます。
final IMyService mockMyService = mock(IMyService.class); // ⭐︎1
try(final MockedStatic<IMyService.Stub> mockedStatic = mockStatic(IMyService.Stub.class)) {
// ↓IMyService.Stub.asInterface()の戻り値がmock化したIMyService(⭐︎1)になります。
mockedStatic.when(() -> IMyService.Stub.asInterface(any())).thenReturn(mockMyService);
// 以下でActivity内などでbindService()してテストしてください。
final ActivityController<MainActivity> controller = buildActivity(MainActivity.class);
controller.create;
...
}
上記操作を行うことで、staticなメソッドのMock化ができます。
なお、上記ではtry-with-resources
で記載しているのですが、try-with-resources
で記載しない場合は、close()を行ってください。
final MockedStatic<IMyService.Stub> mockedStatic = mockStatic(IMyService.Stub.class);
...
mockedStatic.close();
ついでに
メソッド内でnew
されるクラスのMock化もMockitoでできます。
final MockedConstruction<SubClass> mockedConstruction = mockConstruction(SubClass.class);
// 以下でnewされたクラスを取得することができます
// 取得したクラスはMock化されているので、when()を使って戻り値などを変化させることができます。
List<SubClass> constructed = mockedConstruction.constructed();
mockedConstruction.close();
最後に
初投稿なのでうまく説明できているか正直自信がありません。
少しでも誰かのためになれれば幸いです。
今回紹介したMock化方法はほんの一部です。
MockedStatic
もMockedConstruction
もコンストラクタが何種類か存在するので、Mockitoの公式ドキュメントを参考にしつつ、Android StudioなどのIDEで色々と試してみてください。