djUnitの基本
djUnitのVirtual Mock ObjectsとJavaのリフレクションを使用することにより、ビジネスロジックの全てのケースをテストすることができます。
テスト対象のクラス
package org.dyndns.rhmusic;
import java.sql.SQLException;
/**
* djUnitのサンプル用のテスト対象クラス
* @author Paradigm-Shift
*/
public class DjUnitSample {
/**
* 文字列の最後に"&TestRetString"を付加する
* @param message 文字列
* @return 文字列 + "&TestRetString"
* @throws SQLException
*/
public String retString(final String message) throws SQLException {
String ret = message + "&TestRetString";
ret = retMessage(ret);
return ret;
}
/**
* 文字列の最後に"&TestRetMessage"を付加する
* @param message 文字列
* @return 文字列 + "&TestRetMessage"
* @throws SQLException
*/
private String retMessage(final String message) throws SQLException {
if ("".equals(message) || message == null) {
throw new SQLException("error!!");
}
return message + "&TestRetMessage";
}
}
import java.sql.SQLException;
/**
* djUnitのサンプル用のテスト対象クラス
* @author Paradigm-Shift
*/
public class DjUnitSample {
/**
* 文字列の最後に"&TestRetString"を付加する
* @param message 文字列
* @return 文字列 + "&TestRetString"
* @throws SQLException
*/
public String retString(final String message) throws SQLException {
String ret = message + "&TestRetString";
ret = retMessage(ret);
return ret;
}
/**
* 文字列の最後に"&TestRetMessage"を付加する
* @param message 文字列
* @return 文字列 + "&TestRetMessage"
* @throws SQLException
*/
private String retMessage(final String message) throws SQLException {
if ("".equals(message) || message == null) {
throw new SQLException("error!!");
}
return message + "&TestRetMessage";
}
}
テストケース
上のクラスをテストするテストケースです。 このケースだとVirtual Mock Objectsを使用しなくても全てのケースをテストすることができますが、retStringメソッドが確実に動くことが前提になるので厳密なテストとは言えません。 そこでVirtual Mock Objectsを使用することでretStringメソッドの動作が保証でき、厳密なテストが行えます。
package org.dyndns.rhmusic;
import java.lang.reflect.Method;
import java.sql.SQLException;
import jp.co.dgic.testing.framework.DJUnitTestCase;
/**
* <p>DjUnitSampleのテスト</p>
* @author Paradigm-Shift
*/
public class DjUnitSampleTest extends DJUnitTestCase {
/**
* <p>テストの準備</p>
*
* @param name
*/
public DjUnitSampleTest(final String name) {
super(name);
}
/**
* <p>テストの前処理</p>
* <p>テストメソッドが一つ呼ばれる前に毎回実行される</p>
*/
@Override
protected void setUp() throws Exception {
super.setUp();
}
/**
* <p>テストの後処理</p>
* <p>テストメソッドが一つ呼ばれた後に毎回実行される</p>
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
////////////////////////////// ここまでは定型文 //////////////////////////////////
/**
* <p>retStringメソッドが正常に動くケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>test.DjUnitSample#retStringを実行</li>
* <li>Exceptionが発生せず、期待した値が返ってくる</li>
* </ul>
*/
public void testRetStringSuccess() {
final String message = "DjUnitSample";
final DjUnitSample sample = new DjUnitSample();
try {
final String retMessage = sample.retString(message);
//値の検証
assertEquals(retMessage, message + "&TestRetString" + "&TestRetMessage");
} catch (final Exception e) {
e.printStackTrace();
//Exceptionが発生したのでテスト失敗
fail("エラー");
}
}
/**
* <p>retStringメソッドでExceptionが発生するケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>test.DjUnitSample#retStringを実行</li>
* <li>Exceptionが発生し、期待したエラーメッセージが入っている</li>
* </ul>
*/
public void testRetStringException() {
final String message = "DjUnitSample";
final DjUnitSample sample = new DjUnitSample();
try {
//DjUnitSampleクラスのretStringメソッドからExceptionを投げる
addReturnValue("DjUnitSample", "retString", new SQLException("エラーです"));
//メソッドを実行
sample.retString(message);
//期待したExceptionが発生しなければ実行され、テストは失敗
fail("エラー : 期待するExceptionが発生していません");
} catch (final Exception e) {
//エラーが期待した型かどうかを検証
assertTrue(e instanceof SQLException);
//値の検証
assertEquals(e.getMessage(), "エラーです");
}
}
/**
* <p>retMessageメソッドが正常に動くケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>リフレクションを使用し、privateなtest.DjUnitSample#retMessageを実行</li>
* <li>Exceptionが発生せず、期待した値が返ってくる</li>
* </ul>
*/
public void testRetMessageSuccess() {
final String message = "DjUnitSample";
try {
//クラスを呼び出す
final Class clazz = Class.forName("test.DjUnitSample");
//インスタンスを生成
final Object obj = clazz.newInstance();
//パラメータの型を宣言
final Class[] argTypes = {String.class};
//privateメソッドの呼び出し
final Method method = clazz.getDeclaredMethod("retMessage", argTypes);
//privateなメソッドをアクセス可能にする
method.setAccessible(true);
//メソッドに渡すパラメータ
final Object[] args = {message};
//メソッドを実行
final String retMessage = (String)method.invoke(obj, args);
//値の検証
assertEquals(retMessage, message + "&TestRetMessage");
} catch (final Exception e) {
e.printStackTrace();
//Exceptionが発生したのでテスト失敗
fail("エラー");
}
}
/**
* <p>retMessageメソッドでExceptionが発生するケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>リフレクションを使用し、privateなtest.DjUnitSample#retMessageを実行</li>
* <li>Exceptionが発生し、期待したエラーメッセージが入っている</li>
* </ul>
*/
public void testRetMessageExcxeption() {
final String message = null;
try {
//クラスを呼び出す
final Class djClass = DjUnitSample.class;
//インスタンスを生成
final Object obj = djClass.newInstance();
//パラメータの型を宣言
final Class[] argTypes = {String.class};
//privateメソッドの呼び出し
final Method method = djClass.getDeclaredMethod("retMessage", argTypes);
//privateなメソッドをアクセス可能にする
method.setAccessible(true);
//メソッドに渡すパラメータ
final Object[] args = {message};
//メソッドを実行
method.invoke(obj, args);
//期待したExceptionが発生しなければ実行され、テストは失敗
fail("エラー : 期待するExceptionが発生していません");
} catch (final Exception e) {
//エラーメッセージの検証
//エラーが期待した型かどうかを検証
assertTrue(e.getCause() instanceof SQLException);
//Method#invokeでエラーが発生するので、値の比較はgetCause()で行う
assertEquals(e.getCause().getMessage(), "error!!");
}
}
}
import java.lang.reflect.Method;
import java.sql.SQLException;
import jp.co.dgic.testing.framework.DJUnitTestCase;
/**
* <p>DjUnitSampleのテスト</p>
* @author Paradigm-Shift
*/
public class DjUnitSampleTest extends DJUnitTestCase {
/**
* <p>テストの準備</p>
*
* @param name
*/
public DjUnitSampleTest(final String name) {
super(name);
}
/**
* <p>テストの前処理</p>
* <p>テストメソッドが一つ呼ばれる前に毎回実行される</p>
*/
@Override
protected void setUp() throws Exception {
super.setUp();
}
/**
* <p>テストの後処理</p>
* <p>テストメソッドが一つ呼ばれた後に毎回実行される</p>
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
////////////////////////////// ここまでは定型文 //////////////////////////////////
/**
* <p>retStringメソッドが正常に動くケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>test.DjUnitSample#retStringを実行</li>
* <li>Exceptionが発生せず、期待した値が返ってくる</li>
* </ul>
*/
public void testRetStringSuccess() {
final String message = "DjUnitSample";
final DjUnitSample sample = new DjUnitSample();
try {
final String retMessage = sample.retString(message);
//値の検証
assertEquals(retMessage, message + "&TestRetString" + "&TestRetMessage");
} catch (final Exception e) {
e.printStackTrace();
//Exceptionが発生したのでテスト失敗
fail("エラー");
}
}
/**
* <p>retStringメソッドでExceptionが発生するケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>test.DjUnitSample#retStringを実行</li>
* <li>Exceptionが発生し、期待したエラーメッセージが入っている</li>
* </ul>
*/
public void testRetStringException() {
final String message = "DjUnitSample";
final DjUnitSample sample = new DjUnitSample();
try {
//DjUnitSampleクラスのretStringメソッドからExceptionを投げる
addReturnValue("DjUnitSample", "retString", new SQLException("エラーです"));
//メソッドを実行
sample.retString(message);
//期待したExceptionが発生しなければ実行され、テストは失敗
fail("エラー : 期待するExceptionが発生していません");
} catch (final Exception e) {
//エラーが期待した型かどうかを検証
assertTrue(e instanceof SQLException);
//値の検証
assertEquals(e.getMessage(), "エラーです");
}
}
/**
* <p>retMessageメソッドが正常に動くケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>リフレクションを使用し、privateなtest.DjUnitSample#retMessageを実行</li>
* <li>Exceptionが発生せず、期待した値が返ってくる</li>
* </ul>
*/
public void testRetMessageSuccess() {
final String message = "DjUnitSample";
try {
//クラスを呼び出す
final Class clazz = Class.forName("test.DjUnitSample");
//インスタンスを生成
final Object obj = clazz.newInstance();
//パラメータの型を宣言
final Class[] argTypes = {String.class};
//privateメソッドの呼び出し
final Method method = clazz.getDeclaredMethod("retMessage", argTypes);
//privateなメソッドをアクセス可能にする
method.setAccessible(true);
//メソッドに渡すパラメータ
final Object[] args = {message};
//メソッドを実行
final String retMessage = (String)method.invoke(obj, args);
//値の検証
assertEquals(retMessage, message + "&TestRetMessage");
} catch (final Exception e) {
e.printStackTrace();
//Exceptionが発生したのでテスト失敗
fail("エラー");
}
}
/**
* <p>retMessageメソッドでExceptionが発生するケースのテスト</p>
* <p><h2>シナリオ</h2></p>
* <ul>
* <li>リフレクションを使用し、privateなtest.DjUnitSample#retMessageを実行</li>
* <li>Exceptionが発生し、期待したエラーメッセージが入っている</li>
* </ul>
*/
public void testRetMessageExcxeption() {
final String message = null;
try {
//クラスを呼び出す
final Class djClass = DjUnitSample.class;
//インスタンスを生成
final Object obj = djClass.newInstance();
//パラメータの型を宣言
final Class[] argTypes = {String.class};
//privateメソッドの呼び出し
final Method method = djClass.getDeclaredMethod("retMessage", argTypes);
//privateなメソッドをアクセス可能にする
method.setAccessible(true);
//メソッドに渡すパラメータ
final Object[] args = {message};
//メソッドを実行
method.invoke(obj, args);
//期待したExceptionが発生しなければ実行され、テストは失敗
fail("エラー : 期待するExceptionが発生していません");
} catch (final Exception e) {
//エラーメッセージの検証
//エラーが期待した型かどうかを検証
assertTrue(e.getCause() instanceof SQLException);
//Method#invokeでエラーが発生するので、値の比較はgetCause()で行う
assertEquals(e.getCause().getMessage(), "error!!");
}
}
}