JMockitを使ってみる
JMockitを使ってみました。ネット上では”Java最強の単体テストライブラリ”との呼び声が散見されます。
インストール方法や簡単の使用方法は、id:torutkさんの[id:torutk:20101003]を参考にさせていただきました。以下に記すコードも、[id:torutk:20101003]に掲載されているコードをほとんどそのまま使わせてもらっています。
参考としてコードの内容をクラス図にしたのが下の絵です。
単体テストのテストケースとして、同値分割と境界値分析から以下のようなテストケースを挙げました。
- 正常系
- 30℃未満(暑くない)
- 30℃以上(暑い)
- 異常系
- 委譲先のWeatherSensorが処理に失敗する
モック(今回はJMockit)を使わないとしたら、テストケース毎にWeatherSensorImplを作成して、テストケース毎にWeatherSensorImplを含むJARファイルを切り替える必要があるかもしれません。
今回は、そのような事態を避けるためJMockitを使います。それが以下のコードです。NonStrictExpectationsブロックがJMockit固有の処理になります。
@Test public void 気温30度以上() { new NonStrictExpectations() { WeatherSensor mockSensor; { SensorFactory.getWeatherSensor(); returns(mockSensor); mockSensor.getTemperature(); returns(30.0); } }; ThresholdMonitor monitor = new ThresholdMonitor(); boolean result = monitor.isHot(); assertEquals(true, result); } @Test(expected= IllegalStateException.class) public void 委譲先のWeatherSensorが処理に失敗する() { new NonStrictExpectations() { WeatherSensor mockSensor; { SensorFactory.getWeatherSensor(); returns(mockSensor); mockSensor.getTemperature(); result = new IllegalStateException(); } }; ThresholdMonitor monitor = new ThresholdMonitor(); boolean result = monitor.isHot(); }
JMockitを使えば、単体テストのために委譲先のWeatherSensorを自前で書き換える必要が無く、NonStrictExpectationsで示すブロック内に”テストのために期待する処理”を記述するだけで済みました。
所感
開発費が少ないあるいは開発期間が短い場合、単体テストが薄くなる傾向があると思います。例えば、ユーザが「動けば良い」と言ってくだされば、単体テストは限定的に行い、結合試験にてビッグバンテストすることもあると思います。
ただし、開発者に任意というケースばかりでなく、例えば、ミッションクリティカルなシステムの場合はユーザが品質保証の方法について厳しいケースがあります。この場合、基本部品としてのクラスに対して、C0/C1/C2を100%網羅するような単体テストを義務づけるケースも少なくないと思います。
契約時には開発者のスキルや事情を勘案してもらえることが少ないと思いますので、単体テストまで言及しているような品質保障体制下で開発を行う場合、開発者は「いかに効率よく単体テストするか」頭を悩ませるものと思います。
モックは、そのような悩みをかなり軽減してくれそうです。
JMockitはかなりのテストケースをカバーできるように見受けられます。”JMockit最強”という説は”JMockitは他のモックライブラリに比べてカバーできるテストケースが最大”と同義だと思われます。