/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.framework.unit;
import java.lang.reflect.Method;
import junit.framework.TestCase;
import org.seasar.framework.exception.NoSuchMethodRuntimeException;
import org.seasar.framework.util.ClassUtil;
import org.seasar.framework.util.MethodUtil;
import org.seasar.framework.util.StringUtil;
/**
* テンプレートメソッドパターンに従った手続きでEasyMockを利用できるようにサポートするクラスです。
*
* @author koichik
*/
public abstract class EasyMockTestCase extends TestCase {
// instance fields
/** EasyMockとの対話をサポートするオブジェクト */
protected EasyMockSupport easyMockSupport = new EasyMockSupport();
/**
* インスタンスを構築します。
*/
public EasyMockTestCase() {
}
/**
* 名前を指定してインスタンスを構築します。
*
* @param name
* テストケースの名前
*/
public EasyMockTestCase(final String name) {
super(name);
}
@Override
public void runBare() throws Throwable {
easyMockSupport.clear();
setUp();
try {
bindFields();
try {
doRunTest();
} finally {
unbindFields();
}
} finally {
tearDown();
}
}
/**
* モックをフィールドにバインディングします。
*
* @throws Throwable
* 何らかの例外またはエラーが発生した場合
*/
protected void bindFields() throws Throwable {
easyMockSupport.bindMockFields(this, null);
}
/**
* テストを実行します。
*
* @throws Throwable
* 何らかの例外またはエラーが発生した場合
*/
protected void doRunTest() throws Throwable {
final boolean recorded = doRecord();
if (recorded) {
easyMockSupport.replay();
}
runTest();
if (recorded) {
easyMockSupport.verify();
easyMockSupport.reset();
}
}
/**
* モックの振る舞いを記録します。
*
* @return モックの振る舞いが記録するメソッドが存在する場合<code>true</code>、存在しない場合<code>false</code>
* @throws Throwable
* 何らかの例外またはエラーが発生した場合
*/
protected boolean doRecord() throws Throwable {
final String targetName = getTargetName();
if (!StringUtil.isEmpty(targetName)) {
try {
final Method method = ClassUtil.getMethod(getClass(), "record"
+ targetName, null);
MethodUtil.invoke(method, this, null);
return true;
} catch (final NoSuchMethodRuntimeException ignore) {
}
}
return false;
}
/**
* テストケースの名前からプレフィックス<code>test</code>を除いた名前を返します。
*
* @return テストケースの名前からプレフィックス<code>test</code>を除いた名前
*/
protected String getTargetName() {
return getName().substring(4);
}
/**
* モックとフィールドのバインディングを解除します。
*/
protected void unbindFields() {
easyMockSupport.unbindMockFields(this);
}
/**
* デフォルトのモックを作成します。
*
* @param <T>
* モックの型
* @param clazz
* モックの対象となるクラス
* @return 作成されたモック
*/
protected <T> T createMock(final Class<T> clazz) {
return easyMockSupport.createMock(clazz);
}
/**
* Niceモードのモックを作成します。
*
* @param <T>
* モックの型
* @param clazz
* モックの対象となるクラス
* @return 作成されたモック
*/
protected <T> T createNiceMock(final Class<T> clazz) {
return easyMockSupport.createNiceMock(clazz);
}
/**
* Strictモードのモックを作成します。
*
* @param <T>
* モックの型
* @param clazz
* モックの対象となるクラス
* @return 作成されたモック
*/
protected <T> T createStrictMock(final Class<T> clazz) {
return easyMockSupport.createStrictMock(clazz);
}
/**
* EasyMockの利用に必要な一連のメソッド呼び出しを1つのテンプレートメソッドとして提供する抽象クラスです。
*
* @author taedium
*/
protected abstract class Subsequence {
/**
* テストを実行します。
* <p>
* テストは次の順序で行われます。
* <ul>
* <li>モックの振る舞いの記録する</li>
* <li>モックのモードをreplayモードに設定する</li>
* <li>モックとのインタラクションを再現する</li>
* <li>モックとのインタラクションを検証する</li>
* <li>モックをリセットする</li>
* </ul>
* </p>
*
* @throws Exception
* 何らかの例外が発生した場合
*/
public void doTest() throws Exception {
record();
EasyMockTestCase.this.easyMockSupport.replay();
replay();
EasyMockTestCase.this.easyMockSupport.verify();
EasyMockTestCase.this.easyMockSupport.reset();
}
/**
* モックの振る舞いを記録します。
*
* @throws Exception
* 何らかの例外が発生した場合
*/
protected void record() throws Exception {
}
/**
* モックとのインタラクションを再現します。
*
* @throws Exception
* 何らかの例外が発生した場合
*/
protected abstract void replay() throws Exception;
}
}