Mockito を使ってメソッドのモックをする普通の方法
public class SomeTest {
private TestTarget mTarget;
@Test
public void something() {
Something something = mock(Something.class);
when(something.hogehoge()).thenReturn("mock");
mTarget.setSomething(something);
mTarget.doit();
// 以後アサーション
}
}
何も難しいことはないですね。
でも、Something#hogehoge()
が@hide
だったらどうでしょう。
当然TestTarget
内でもリフレクションで呼び出すことになりますが、Mockito でモックする場合はどうするのがよいでしょう。
@hide
なメソッドをモックする
まず適当なユーティリティを作ります。
public Utility {
public static final String TAG = Utility.class.getSimpleName();
private Utility() {
throw new AssertionError();
}
public static Object callHiddenMethod(Object target, String methodName, Class[] argTypes, Object[] args) {
try {
Class clazz = target.getClass();
Method method = clazz.getDeclaredMethod(methodName, argTypes);
return method.invoke(target, args);
} catch (NoSuchMethodException e) {
Log.e(TAG, "no method found", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "something went wrong while executing the method.", e);
} catch (IllegalAccessException e) {
Log.e(TAG, "cannot access to the method", e);
}
return null;
}
}
簡単ですね。リフレクションでメソッドを呼び出すためのユーティリティです。
次に、このユーティリティを使って以下のようにテストコードを書きます。
public class SomeTest {
private TestTarget mTarget;
@Test
public void something() {
Something something = mock(Something.class);
when(Utility.callHiddenMethod(something, "hogehoge", null, null)).thenReturn("mock");
mTarget.setSomething(something);
mTarget.doit();
// 以後アサーション
}
}
when
でのメソッド呼び出しの指定をユーティリティのものに置き換えただけですね。簡単ですね。
これでテストを動かしてみると……
BUILD SUCCESSFUL
ちゃんと動きます。やったねたえちゃん!
もっと普通の方法
@hide
なメソッド、たいていはフレームワークが持っているものなので、そのフレームワークのクラスをラップするだけのクラスを作ってそいつをモックするほうがずっとはるかに単純で分かりやすいと思います。