読者です 読者をやめる 読者になる 読者になる

こいばな - riskriskと時々鼻メガネ -

正式名称は「どすこい!鼻メガネ会長のいつでも土俵際!」です。ソフトウェア開発に関することを書いています。

JUnitでMockしたい(Mockito)

Junit使ってて、Mock使いたくなったので、Android環境でのJunitテスト環境に
Mockitoを入れてみました。

入れ方自体は簡単で、幾つかjarをlibsに入れるだけで動きます。
libsにjarを入れておけば、勝手に組み込まれてくれるので、それを利用します。

まず、下記の3つのjarをダウンロードしてきます。

Mockito本体

mockito - simpler & better mocking - Google Project Hosting https://code.google.com/p/mockito/

ここから、mockito-all-1.9.5.jar を落としてきます。

それから、Android上で動かす場合、Dailvik VMAndroid用JavaVM)に対応した
ライブラリである必要があるわけで、Mockitoそのままだとよろしくないため
そこら辺を上手く解決してくれる、dexmakerを入れます。
(説明間違えてたらごめんなさい)

dexmaker - Programmatic code generation for Android. - Google Project Hosting http://code.google.com/p/dexmaker/

ここから、dexmaker-1.0.jar と dexmaker-mockito-1.0.jar をダウンロードします。

ダウンロードしてきた3つのファイルを、libsに入れます

f:id:riskrisk:20140211220255p:plain

パッケージエクスプローラーはこんなかんじになります。

あとは、コードに

import static org.mockito.Mockito.*;

のimportを書けば、使えるようになります。

クラスに対して

全体をMockする場合は、 mock()
部分的にMockする場合は、spy()

を利用します。

サンプルコードはこんな感じ

import android.util.Log;
import junit.framework.TestCase;
import static org.mockito.Mockito.*;

public class MockSample extends TestCase {

	private final static String TAG = "MockSample";
	
	protected void setUp() throws Exception {
		super.setUp();
	}

	protected void tearDown() throws Exception {
		super.tearDown();
	}

	public class TargetClass {

		public void printA() {
			Log.d(TAG, "print A");
		}
		
		public void printB() {
			Log.d(TAG, "print B");
		}
	}
	
	public void testMockAndSpy() {

		TargetClass targetMock = mock(TargetClass.class); // Mock
		TargetClass targetSpy = spy(new TargetClass()); // Spy
		
		// Mockは 全部Mockされる
		Log.d(TAG, "Mock");
		targetMock.printA();
		targetMock.printB();
		
		// Spyは部分的にMock出来る
		Log.d(TAG, "Spy");
		doNothing().when(targetSpy).printB();
		targetSpy.printA();
		targetSpy.printB();
	}
	
}

ログは、こんなかんじに出ます。

02-11 13:18:55.254: D/MockSample(9243): Mock
02-11 13:18:55.285: D/MockSample(9243): Spy
02-11 13:18:55.295: D/MockSample(9243): print A

Mock側は全部Mockされたので出力なし
Spy側は、printBだけMockしたのでprintAだけ表示されます。

呼ばれたことの確認とか、呼ばれた時の振る舞いを定義するとかは、また後日。