JMockitを使ってみました

こんにちは、中村です。

某プロジェクトでJMockitを使う機会があったので、使用方法などを紹介したいと思います。
※一番最後に使用する際の注意点があります。

1. JMockitとは

JMockitとは、JUnit中でモックオブジェクトを簡単に作成し、利用できるライブラリです。

例えば、以下の様な現在気温を取得し、取得した気温に応じて返却する値が変化するメソッドを持つクラスがあったとします。

package monitor;
import sensor.TemperatureSensor;
// 現在の気温を取得し、気温が35度以上の場合に異常を検知するクラス。
public class TemperatureMonitor {
	private TemperatureSensor sensor;
	public TemperatureMonitor() {
		sensor = TemperatureSensor.getInstance();
	}
	public boolean calculate() {
		float temp = sensor.getTemporature();
		// 35度を超えていた場合、異常を報告する。
		if (temp >= 35.0) {
			return false;
		}
		return true;
	}
}

以上のクラスのcalculateメソッドのJUnitテストコードを書くと以下のようになります。

package test;
import static org.junit.Assert.*;
import monitor.TemperatureMonitor;
import org.junit.Test;
public class TemperatureMonitorTest {
	@Test
	public void testExtremelyHotDay() {
		TemperatureMonitor monitor = new TemperatureMonitor();

		// 気温が35度を超えた場合の試験を実施したいが、結果は環境に依存するため、
		// テスト側から結果を制御することができない。
		boolean result = monitor.calculate();

		// false(35度以上)の場合に正となる。
		assertFalse(result);
	}
}

試験結果が一定でないため、モックオブジェクトを作成して試験しなくてはなりません。
jMockitを利用することによって、このようなモックオブジェクトを作成しなければ試験できないようなメソッドを、容易に試験することができるようになります。

2. JMockiitを使用するには

JMockitは以下のURLからダウンロードできます。

Downloads – jmockit – A developer testing toolkit for Java – Google Project Hosting
http://code.google.com/p/jmockit/downloads/list 
※私が使用したJMockitのバージョンは0.999.15です。

ダウンロードしたjarファイルをクラスパスに追加すればJMockitを使用できます。

3. JMockitを利用したJUnitテスト

上記のTemperatureMonitorTestクラスをJMockitを利用して実装してみました。

package test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import mockit.Expectations;
import mockit.Mocked;
import monitor.TemperatureMonitor;
import org.junit.Test;
import sensor.TemperatureSensor;
public class TemperatureMonitorTest {

	// @Mockedアノテーションでモック化するクラス(methodsでメソッド名を指定可能)を宣言する。
	// メソッド名を指定することで、他のメソッドはモック化せず使用することができる。
	@Mocked(methods="getTemporature")
	private TemperatureSensor sensor;

	@Test
	public void testExtremelyHotDay() {
		// モック化したクラス(メソッド)の実行結果の実装
		new Expectations() {
			{
				// getTemporature()メソッドが呼ばれた場合
				sensor.getTemporature();
				// 結果は35.5を返す。
				result = 35.5f;
			}
		};
		TemperatureMonitor monitor = new TemperatureMonitor();
		// モックが35.5を返却するので(現在気温が35.5度なので)falseが代入される。
		boolean result = monitor.calculate();
		assertFalse(result);
	}
}

簡単に使用するだけならば、以下の2つの手順だけ でJMockitを利用できます。

  1. モック化するクラス(もしくはメソッド)を宣言する。
  2. モック化したクラスのメソッドの結果を記述する。

○ モック化するクラス(もしくはメソッド)を宣言する

モック化するクラスは、@Mockedアノテーションを付けることで宣言できます。
また、メソッド単体に対して宣言することもできます。
TemperatureMonitorTestクラスの例では、TemperatureSensorクラスのgetTemporatureメソッドを宣言しています。

// @Mockedアノテーションでモック化するクラス(methodsでメソッド名を指定可能)を宣言する。
// メソッド名を指定することで、他のメソッドはモック化せず使用することができる。
@Mocked(methods="getTemporature")
private TemperatureSensor sensor;

TemperatureMonitorTestクラスの例では、クラスメソッドとして宣言しましたが、
1つのテストケースのみモック化しなければならない場合は、テストケース中で宣言することもできます。

// モック化したクラス(メソッド)の実行結果の実装
new Expectations() {
	@Mocked(methods="getTemporature")
	private TemperatureSensor sensor;
	{
		// getTemporature()メソッドが呼ばれた場合
		sensor.getTemporature();
		// 結果は35.5を返す。
		result = 35.5f;
	}
};

○モック化したクラスのメソッドの結果を記述する

モック化したメソッドが呼び出された時の結果を、「Expectations()」の中に記述します。
記述形式は

sensor.getTemporature();  // モック化したメソッド呼び出し
result = 35.5f;           // result = モック化したメソッドが返却する値

となります。
もし、同じメソッドが続けて呼ばれる場合は、メソッド呼び出しを省略することができます。

sensor.getTemporature();
result = 35.5f;
// もう一度sensor.getTemporature()が呼ばれた場合
result = 25.0f;

4. JMockit利用時の注意点

JMockitを使用する場合、クラスパスの設定には、
JMockitのライブラリjarをJUnitのライブラリjarよりも先に設定されていなければなりません。
もし、JMockitのjarがJUnitのjarよりもあとに設定されている場合は、以下のエラーが発生します。

WARNING: JMockit was initialized on demand, which may cause certain tests to fail;
please check the documentation for better ways to get it initialized.

Eclipseで開発している場合、JUnitは同梱されているため、最後にJMockitを追加する事になる可能性が高いとおもいます。その場合、ビルドパスの設定で設定順序を変更することを忘れないようにしてください。

コメントを残す

メールアドレスが公開されることはありません。