確認環境
- Android Studio 1.1
- Android Gradle Plugin 1.1
- JUnit 4.12
- PowerMock 1.6.2
はじめに
Android Studio 1.1(android gradle plugin 1.1)からUnitTestがサポートされた.
今回はPowerMockを使ってstatic methodをモックするUnitTestを書いた.
Android StudioでUnitTestを開始するには下記を参考.
UnitTestの準備が整ったならモジュールのbuild.gradleに下記の依存ライブラリを記述する.
// UnitTestにはtestCompileキーワードを使用
testCompile 'junit:junit:4.12'
// PowerMockのライブラリを指定
testCompile 'org.powermock:powermock-module-junit4:1.6.2'
testCompile 'org.powermock:powermock-api-mockito:1.6.2'
次はoptionだが, Android StudioのUnitTestは実行時にandroid.jarのモックとなるmockable-android*.jar
を作成する.
ここで定義されるメソッドスタブはすべてRuntimeExceptionをスローするように実装される.
これをExceptionではなくDefault value(false etc.)を返却するように変更するには下記を指定する.
testOptions {
unitTests.returnDefaultValues = true
}
あとはいつもの方法でPowerMockを使えばOK.
- TestRunnerにPowerMockRunnerを指定
@RunWith(PowerMockRunner.class)
public class MyTestCase extends TestCase {
- TestCaseを継承したクラスにアノテーションを追加
@RunWith(PowerMockRunner.class)
@PrepareForTest(Static.class) // Staticメソッドをモックするクラスを指定(,で複数指定可)
public class MyTestCase extends TestCase {
テストコード
@Test
public void testMockStaticMethod() throws Exception {
assertFalse("オリジナルはfalseを返す", Target.staticBoolean());
PowerMockito.mockStatic(Target.class);
when(Target.staticBoolean()).thenReturn(true);
assertTrue("モックはtrueを返す", Target.staticBoolean());
verifyStatic(times(1));
}
@Test
public void testMockConstructor() throws Exception {
assertEquals("Valueは引数なしのコンストラクタで初期化される",
new Value(), new Target().getValue());
Value mockValue = new Value(100);
assertNotEquals("引数ありで初期化されたValueとでは等価ではなくなる",
mockValue, new Target().getValue());
PowerMockito.whenNew(Value.class).withNoArguments().thenReturn(mockValue);
assertEquals("Valueの引数なしコンストラクタでモックが返される",
mockValue, new Target().getValue());
verifyNew(Value.class).withNoArguments();
mockValue = new Value(500);
assertEquals("Valueの引数ありコンストラクタはモックされていない",
mockValue, new Value(500));
mockValue = new Value(1000);
PowerMockito.whenNew(Value.class).withArguments(anyInt()).thenReturn(mockValue);
assertEquals("Valueの引数ありコンストラクタもモックされる",
mockValue, new Target(500).getValue());
verifyNew(Value.class, atLeastOnce()).withArguments(anyInt());
}
@Test
public void testLogger() throws Exception {
PowerMockito.mockStatic(Log.class);
Mockito.when(Log.isLoggable(anyString(), anyInt())).thenReturn(true);
assertTrue("モックしてtrueを返す", Log.isLoggable("mocktag", Log.VERBOSE));
assertTrue(BuildConfig.DEBUG);
// static finalな定数をreflectionで変更.
Field field = BuildConfig.class.getField("DEBUG");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, false);
assertFalse(BuildConfig.DEBUG);
}
以上.