[[SeasarJavadocProject]]
*S2TestCase [#f1ceb097]
2.0.22 反映済み~
&ref("S2TestCase.java");
#code(Java)<<EOF
package org.seasar.extension.unit;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;
import javax.transaction.TransactionManager;

import junit.framework.Assert;
import junit.framework.TestCase;

import org.seasar.extension.dataset.ColumnType;
import org.seasar.extension.dataset.DataReader;
import org.seasar.extension.dataset.DataRow;
import org.seasar.extension.dataset.DataSet;
import org.seasar.extension.dataset.DataTable;
import org.seasar.extension.dataset.DataWriter;
import org.seasar.extension.dataset.impl.SqlDeleteTableWriter;
import org.seasar.extension.dataset.impl.SqlReloadReader;
import org.seasar.extension.dataset.impl.SqlReloadTableReader;
import org.seasar.extension.dataset.impl.SqlTableReader;
import org.seasar.extension.dataset.impl.SqlWriter;
import org.seasar.extension.dataset.impl.XlsReader;
import org.seasar.extension.dataset.impl.XlsWriter;
import org.seasar.extension.dataset.types.ColumnTypes;
import org.seasar.extension.jdbc.UpdateHandler;
import org.seasar.extension.jdbc.impl.BasicUpdateHandler;
import org.seasar.framework.container.ComponentDef;
import org.seasar.framework.container.ContainerConstants;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;
import org.seasar.framework.container.impl.S2ContainerImpl;
import org.seasar.framework.exception.EmptyRuntimeException;
import org.seasar.framework.exception.NoSuchMethodRuntimeException;
import org.seasar.framework.util.ClassUtil;
import org.seasar.framework.util.ConnectionUtil;
import org.seasar.framework.util.DataSourceUtil;
import org.seasar.framework.util.FieldUtil;
import org.seasar.framework.util.FileOutputStreamUtil;
import org.seasar.framework.util.MethodUtil;
import org.seasar.framework.util.ResourceUtil;
import org.seasar.framework.util.StringUtil;

/**
 * <p>JUnitのTestCaseを拡張した、S2を使ったテストを楽しくおこなうための
 * クラスです。</p>
 *
 * <p>各テストメソッドを実行する際には、以下の順番で処理をおこないます。
 * テストメソッド名が関係する処理がありますので、ここではtestXxx()という
 * テストメソッドを実行すると仮定します。</p>
 *
 * <ol>
 * <li>S2Containerのインスタンスを作成します。</li>
 * <li>setUp()を実行します。</li>
 * <li>setUpXxxという名前のメソッドがあれば実行します。</li>
 * <li>S2Containerを初期化します。</li>
 * <li>"j2ee.dataSource"という名前のデータソースをコンテナから取得します。</li>
 * <li>setUpAfterContainerInit()を実行します。</li>
 * <li>フィールドにDIをおこないます。</li>
 * <li>testXxx()を実行します。</li>
 * <li>tearDownBeforeContainerDestroy()を実行します。</li>
 * <li>データソースを開放します。</li>
 * <li>S2Containerの終了処理をおこないます。</li>
 * <li>tearDownXxx()という名前のメソッドがあれば実行します。</li>
 * <li>tearDown()を実行します。</li>
 * </ol>
 *
 * <p>setUp()内、またはsetUpXxx()内でinclude("j2ee.dicon")を行い、テスト
 * メソッド名の最後に"Tx"と付けると、テストメソッドの実行前にトランザク
 * ションを開始し、テストメソッドの終了後にトランザクションをロールバック
 * します。DBのレコードを変更するようなテストの場合にこの機能を利用すると、
 * クリーンアップ処理が不要になります。</p>
 *
 * @author higa
 * @see junit.framework.TestCase
 */
public class S2TestCase extends TestCase {

    private static final String DATASOURCE_NAME = "j2ee"
            + ContainerConstants.NS_SEP + "dataSource";

    private S2Container container_;

    private DataSource dataSource_;

    private Connection connection_;

    private DatabaseMetaData dbMetaData_;

    private List bindedFields_;

    /**
     * <p>指定された名前でテストケースを作成します。</p>
     *
     * @param name テストケースの名前
     */
    public S2TestCase(String name) {
        super(name);
    }

    /**
     * <p>テストケースが保有するS2コンテナを取得します。</p>
     *
     * @return S2コンテナ
     */
    public S2Container getContainer() {
        return container_;
    }

    /**
     * <p>コンポーネント名を指定してS2コンテナからコンポーネントを取得
     * します。</p>
     * <p>指定した名前を持つコンポーネントが登録されていない場合はnullを
     * 返します。</p>
     *
     * @param componentName 取得するコンポーネント名
     * @return 指定した名前を持つコンポーネント
     * @see org.seasar.framework.container.S2Container#getComponent(java.lang.Object)
     */
    public Object getComponent(String componentName) {
        return container_.getComponent(componentName);
    }

    /**
     * <p>クラスを指定してS2コンテナからコンポーネントを取得します。</p>
     * <p>インターフェースを指定した場合はそのインターフェースを実装して
     * いるコンポーネント、クラスを指定した場合はそのクラスかそのクラスを
     * 親に持つ子クラスのコンポーネントを取得します。</p>
     * <p>指定したクラスのコンポーネントが登録されていない場合はnullを
     * 返します。</p>
     *
     * @param componentClass 取得するクラス
     * @return 指定したクラスのコンポーネント
     * @see org.seasar.framework.container.S2Container#getComponent(java.lang.Object)
     */
    public Object getComponent(Class componentClass) {
        return container_.getComponent(componentClass);
    }

    /**
     * <p>コンポーネント名を指定してS2コンテナからコンポーネント定義を
     * 取得します。</p>
     *
     * @param componentName 取得するコンポーネント名
     * @return 指定した名前を持つコンポーネント定義
     * @see org.seasar.framework.container.S2Container#getComponentDef(java.lang.Object)
     */
    public ComponentDef getComponentDef(String componentName) {
        return container_.getComponentDef(componentName);
    }

    /**
     * <p>クラスを指定してS2コンテナからコンポーネント定義を取得します。
     * </p>
     *
     * @param componentClass 取得するクラス
     * @return 指定したクラスのコンポーネント定義
     * @see org.seasar.framework.container.S2Container#getComponentDef(java.lang.Object)
     */
    public ComponentDef getComponentDef(Class componentClass) {
        return container_.getComponentDef(componentClass);
    }

    /**
     * <p>クラスをS2コンテナにコンポーネント定義として登録します。</p>
     *
     * @param componentClass コンポーネントのクラス
     * @see org.seasar.framework.container.S2Container#register(java.lang.Class)
     */
    public void register(Class componentClass) {
        container_.register(componentClass);
    }

    /**
     * <p>クラスをS2コンテナに名前付きコンポーネント定義として登録
     * します。</p>
     *
     * @param componentClass コンポーネントのクラス
     * @param componentName コンポーネントの名前
     * @see org.seasar.framework.container.S2Container#register(java.lang.Class, java.lang.String)
     */
    public void register(Class componentClass, String componentName) {
        container_.register(componentClass, componentName);
    }

    /**
     * <p>オブジェクトをS2コンテナにコンポーネントとして登録します。</p>
     * <p>キーはオブジェクトのクラスになります。</p>
     *
     * @param component コンポーネントとして登録するオブジェクト
     * @see org.seasar.framework.container.S2Container#register(java.lang.Object)
     */
    public void register(Object component) {
        container_.register(component);
    }

    /**
     * <p>オブジェクトをS2コンテナに名前付きコンポーネントとして登録
     * します。</p>
     *
     * @param component コンポーネントとして登録するオブジェクト
     * @param componentName コンポーネント名
     * @see org.seasar.framework.container.S2Container#register(java.lang.Object, java.lang.String)
     */
    public void register(Object component, String componentName) {
        container_.register(component, componentName);
    }

    /**
     * <p>S2コンテナにコンポーネント定義を登録します。</p>
     *
     * @param componentDef 登録するコンポーネント定義
     * @see org.seasar.framework.container.S2Container#register(org.seasar.framework.container.ComponentDef)
     */
    public void register(ComponentDef componentDef) {
        container_.register(componentDef);
    }

    /**
     * <p>設定ファイルのパスを指定して子コンテナをincludeします。</p>
     * <p>パスはCLASSPATHで指定されているディレクトリをルートとする
     * 設定ファイルの絶対パスか、ファイル名のみを指定します。</p>
     * <p>ファイル名のみの場合、テストケースと同じパッケージにあるもの
     * とします。</p>
     *
     * @param path 子コンテナの設定ファイルのパス
     */
    public void include(String path) {
        S2ContainerFactory.include(container_, convertPath(path));
    }

    private String convertPath(String path) {
        if (ResourceUtil.getResourceNoException(path) != null) {
            return path;
        } else {
            String prefix = getClass().getPackage().getName().replace('.', '/');
            return prefix + "/" + path;
        }
    }

    /**
     * <p>データソースを取得します。</p>
     *
     * @return データソース
     */
    public DataSource getDataSource() {
        if (dataSource_ == null) {
            throw new EmptyRuntimeException("dataSource");
        }
        return dataSource_;
    }

    /**
     * <p>データソースからコネクションを取得します。</p>
     *
     * @return データソースから取得したコネクション
     */
    public Connection getConnection() {
        if (connection_ != null) {
            return connection_;
        }
        connection_ = DataSourceUtil.getConnection(getDataSource());
        return connection_;
    }

    /**
     * <p>コネクションのデータベースメタデータを取得します。</p>
     *
     * @return コネクションのデータベースメタデータ
     */
    public DatabaseMetaData getDatabaseMetaData() {
        if (dbMetaData_ != null) {
            return dbMetaData_;
        }
        dbMetaData_ = ConnectionUtil.getMetaData(getConnection());
        return dbMetaData_;
    }

    /**
     * <p>Excelファイルを読み、DataSetを作成します。</p>
     * <p>シート名をテーブル名、一行目をカラム名、二行目以降をデータ
     * として読み込みます。</p>
     *
     * <p>パスはCLASSPATHで指定されているディレクトリをルートとする
     * 設定ファイルの絶対パスか、ファイル名のみを指定します。ファイル名
     * のみの場合、テストケースと同じパッケージにあるものとします。</p>
     *
     * @param path Excelファイルのパス
     * @return Excelファイルの内容から作成したDataSet
     * @see org.seasar.extension.dataset.impl.XlsReader#read()
     */
    public DataSet readXls(String path) {
        DataReader reader = new XlsReader(convertPath(path));
        return reader.read();
    }

    /**
     * <p>DataSetの内容から、Excelファイルを作成します。</p>
     * <p>シート名にテーブル名、一行目にカラム名、二行目以降にデータ
     * を書き込みます。</p>
     *
     * <p>パスはCLASSPATHで指定されているディレクトリをルートとする
     * 設定ファイルの絶対パスか、ファイル名のみを指定します。ファイル
     * 名のみの場合、テストケースと同じパッケージにあるものとします。</p>
     *
     * @param path Excelファイルのパス
     * @param dataSet Excelファイルに書き込む内容のDataSet
     * @see org.seasar.extension.dataset.impl.XlsWriter#write(DataSet)
     */
    public void writeXls(String path, DataSet dataSet) {
        File dir = ResourceUtil.getBuildDir(getClass());
        File file = new File(dir, convertPath(path));
        DataWriter writer = new XlsWriter(FileOutputStreamUtil.create(file));
        writer.write(dataSet);
    }

    /**
     * <p>DataSetをDBに書き込みます。</p>
     *
     * @param dataSet データベースに書き込む内容のDataSet
     * @see org.seasar.extension.dataset.impl.SqlWriter#write(DataSet)
     */
    public void writeDb(DataSet dataSet) {
        DataWriter writer = new SqlWriter(getDataSource());
        writer.write(dataSet);
    }

    /**
     * <p>DBからレコードを読み込み、DataTableを作成します。</p>
     *
     * @param table 読み込むテーブル名
     * @return 読み込んだ内容から作成したDataTable
     * @see org.seasar.extension.dataset.impl.SqlTableReader#read()
     */
    public DataTable readDbByTable(String table) {
        return readDbByTable(table, null);
    }

    /**
     * <p>DBからレコードを読み込み、DataTableを作成します。</p>
     * <p>読み込むレコードはconditionの条件を満たすレコードです。
     * conditionには" WHERE "より後ろをセットしてください。</p>
     *
     * @param table 読み込むテーブル名
     * @param condition 条件句(WHEREの後ろ)
     * @return 読み込んだ内容から作成したDataTable
     * @see org.seasar.extension.dataset.impl.SqlTableReader#read()
     */
    public DataTable readDbByTable(String table, String condition) {
        SqlTableReader reader = new SqlTableReader(getDataSource());
        reader.setTable(table, condition);
        return reader.read();
    }

    /**
     * <p>DBからSQL文の実行結果を取得し、DataTableを作成します。</p>
     * <p>作成したDataTableのテーブル名はtableNameになります。</p>
     *
     * @param sql 実行するSQL文
     * @param tableName 作成するDataTableのテーブル名
     * @return 読み出した内容のDataTable
     * @see org.seasar.extension.dataset.impl.SqlTableReader#read()
     */
    public DataTable readDbBySql(String sql, String tableName) {
        SqlTableReader reader = new SqlTableReader(getDataSource());
        reader.setSql(sql, tableName);
        return reader.read();
    }

    /**
     * <p>Excelファイルを読み込み、DBに書き込みます。</p>
     * <p>シート名をテーブル名、一行目をカラム名、二行目以降をデータ
     * として読み込みます。</p>
     *
     * <p>パスはCLASSPATHで指定されているディレクトリをルートとする
     * 設定ファイルの絶対パスか、ファイル名のみを指定します。ファイル名
     * のみの場合、テストケースと同じパッケージにあるものとします。</p>
     *
     * @param path Excelファイルのパス
     * @see org.seasar.extension.dataset.impl.XlsReader#read()
     * @see org.seasar.extension.dataset.impl.SqlWriter#write(DataSet)
     */
    public void readXlsWriteDb(String path) {
        writeDb(readXls(path));
    }

    /**
     * <p>Excelファイルを読み込み、DBに書き込みます。</p>
     * <p>シート名をテーブル名、一行目をカラム名、二行目以降をデータ
     * として読み込みます。</p>
     *
     * <p>Excelの内容とDBのレコードとで主キーが一致するものがあれば、
     * そのレコードを削除した後に書き込みます。</p>
     *
     * <p>パスはCLASSPATHで指定されているディレクトリをルートとする
     * 設定ファイルの絶対パスか、ファイル名のみを指定します。ファイル名
     * のみの場合、テストケースと同じパッケージにあるものとします。</p>
     *
     * @param path Excelファイルのパス
     * @see org.seasar.extension.dataset.impl.XlsReader#read()
     * @see org.seasar.extension.dataset.impl.SqlWriter#write(DataSet)
     */
    public void readXlsReplaceDb(String path) {
        DataSet dataSet = readXls(path);
        deleteDb(dataSet);
        writeDb(dataSet);
    }

    /**
     * <p>Excelファイルを読み込み、DBに書き込みます。</p>
     * <p>シート名をテーブル名、一行目をカラム名、二行目以降をデータ
     * として読み込みます。</p>
     *
     * <p>対象となるテーブルのレコードを全て削除した後に書き込みます。
     * </p>
     *
     * <p>パスはCLASSPATHで指定されているディレクトリをルートとする
     * 設定ファイルの絶対パスか、ファイル名のみを指定します。ファイル名
     * のみの場合、テストケースと同じパッケージにあるものとします。</p>
     *
     * @see org.seasar.extension.dataset.impl.XlsReader#read()
     * @see org.seasar.extension.dataset.impl.SqlWriter#write(DataSet)
     */
    public void readXlsAllReplaceDb(String path) {
        DataSet dataSet = readXls(path);
        for (int i = dataSet.getTableSize() - 1; i >= 0; --i) {
            deleteTable(dataSet.getTable(i).getTableName());
        }
        writeDb(dataSet);
    }

    /**
     * <p>DataSetに対応するDBのレコードを読み込み、DataSetを作成します
     * 。</p>
     *
     * @param dataSet 対象DBに対応するDataSet
     * @return 最新状態のDataSet
     * @see org.seasar.extension.dataset.impl.SqlReloadReader#read()
     */
    public DataSet reload(DataSet dataSet) {
        return new SqlReloadReader(getDataSource(), dataSet).read();
    }

    /**
     * <p>DataTableに対応するDBのレコードを読み込み、DataTableを作成
     * します。</p>
     *
     * @param table 対象DBに対応するDataTable
     * @return 最新状態のDataTable
     * @see org.seasar.extension.dataset.impl.SqlReloadTableReader#read()
     */
    public DataTable reload(DataTable table) {
        return new SqlReloadTableReader(getDataSource(), table).read();
    }

    /**
     * <p>DataSetに対応するDBのレコードを削除します。</p>
     *
     * @param dataSet 対象DBに対応するDataSet
     * @see org.seasar.extension.dataset.impl.SqlDeleteTableWriter#write(DataTable)
     */
    public void deleteDb(DataSet dataSet) {
        SqlDeleteTableWriter writer = new SqlDeleteTableWriter(getDataSource());
        for (int i = dataSet.getTableSize() - 1; i >= 0; --i) {
            writer.write(dataSet.getTable(i));
        }
    }

    /**
     * <p>DBから指定するテーブルの全レコードを削除します。</p>
     *
     * @param tableName 削除対象のテーブル名
     */
    public void deleteTable(String tableName) {
        UpdateHandler handler = new BasicUpdateHandler(getDataSource(),
                "DELETE FROM " + tableName);
        handler.execute(null);
    }

    /**
     * <p>DataSet同士を比較します。</p>
     * <p>カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param expected 予測値
     * @param actual 実際値
     */
    public void assertEquals(DataSet expected, DataSet actual) {
        assertEquals(null, expected, actual);
    }

    /**
     * <p>DataSet同士を比較します。</p>
     * <p>カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param message assert失敗時のメッセージ
     * @param expected 予測値
     * @param actual 実際値
     */
    public void assertEquals(String message, DataSet expected, DataSet actual) {
        message = message == null ? "" : message;
        assertEquals(message + ":TableSize", expected.getTableSize(), actual
                .getTableSize());
        for (int i = 0; i < expected.getTableSize(); ++i) {
            assertEquals(message, expected.getTable(i), actual.getTable(i));
        }
    }

    /**
     * <p>DataTable同士を比較します。</p>
     * <p>カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param expected 予測値
     * @param actual 実際値
     */
    public void assertEquals(DataTable expected, DataTable actual) {
        assertEquals(null, expected, actual);
    }

    /**
     * </p>DataTable同士を比較します。</p>
     * <p>カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param message assert失敗時のメッセージ
     * @param expected 予測値
     * @param actual 実際値
     */
    public void assertEquals(String message, DataTable expected,
            DataTable actual) {

        message = message == null ? "" : message;
        assertEquals(message + ":RowSize", expected.getRowSize(), actual
                .getRowSize());
        for (int i = 0; i < expected.getRowSize(); ++i) {
            DataRow expectedRow = expected.getRow(i);
            DataRow actualRow = actual.getRow(i);

            for (int j = 0; j < expected.getColumnSize(); ++j) {
                String columnName = expected.getColumnName(j);
                Object expectedValue = expectedRow.getValue(columnName);
                ColumnType ct = ColumnTypes.getColumnType(expectedValue);
                Object actualValue = actualRow.getValue(columnName);
                if (!ct.equals(expectedValue, actualValue)) {
                    assertEquals(message + ":Row=" + i + ":columnName="
                            + columnName, expectedValue, actualValue);
                }
            }
        }
    }

    /**
     * <p>オブジェクトをDataSetと比較します。</p>
     * <p>オブジェクトは、Bean、Map、BeanのList、MapのListのいずれか
     * でなければなりません。</p>
     *
     * </p>Beanの場合はプロパティ名を、Mapの場合はキーをカラム名として
     * 比較します。<br>
     * カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param expected 予測値
     * @param actual 実際値
     */
    public void assertEquals(DataSet expected, Object actual) {
        assertEquals(null, expected, actual);
    }

    /**
     * <p>オブジェクトをDataSetと比較します。</p>
     * <p>オブジェクトは、Bean、Map、BeanのList、MapのListのいずれか
     * でなければなりません。</p>
     *
     * <p>Beanの場合はプロパティ名を、Mapの場合はキーをカラム名として
     * 比較します。<br>
     * カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param message assert失敗時のメッセージ
     * @param expected 予測値
     * @param actual 実際値
     */
    public void assertEquals(String message, DataSet expected, Object actual) {
        Assert.assertNotNull(expected);
        Assert.assertNotNull(actual);

        Class beanClass = null;
        if (actual instanceof List) {
            List actualList = (List) actual;
            Assert.assertFalse(actualList.isEmpty());
            Object actualItem = actualList.get(0);
            if (actualItem instanceof Map) {
                assertMapListEquals(message, expected, actualList);
            } else {
                assertBeanListEquals(message, expected, actualList);
            }
        } else {
            if (actual instanceof Map) {
                assertMapEquals(message, expected, (Map) actual);
            } else {
                assertBeanEquals(message, expected, actual);
            }
        }
    }

    /**
     * <p>MapをDataSetと比較します。</p>
     * <p>Mapのキーをカラム名として比較します。<br>
     * カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param message assert失敗時のメッセージ
     * @param expected 予測値
     * @param map 実際値
     */
    protected void assertMapEquals(String message, DataSet expected, Map map) {

        MapReader reader = new MapReader(map);
        assertEquals(message, expected, reader.read());
    }

    /**
     * <p>MapのListをDataSetと比較します。</p>
     * <p>Mapのキーをカラム名として比較します。<br>
     * カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param message assert失敗時のメッセージ
     * @param expected 予測値
     * @param list 実際値
     */
    protected void assertMapListEquals(String message, DataSet expected,
            List list) {

        MapListReader reader = new MapListReader(list);
        assertEquals(message, expected, reader.read());
    }

    /**
     * <p>BeanをDataSetと比較します。</p>
     * <p>Beanのプロパティ名をカラム名として比較します。<br>
     * カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param message assert失敗時のメッセージ
     * @param expected 予測値
     * @param bean 実際値
     */
    protected void assertBeanEquals(String message, DataSet expected,
            Object bean) {

        BeanReader reader = new BeanReader(bean);
        assertEquals(message, expected, reader.read());
    }

    /**
     * <p>BeanのListをDataSetと比較します。</p>
     * <p>Beanのプロパティ名をカラム名として比較します。<br>
     * カラムの並び順は比較に影響しません。<br>
     * 数値は全てBigDecimalとして比較します。</p>
     *
     * @param message assert失敗時のメッセージ
     * @param expected 予測値
     * @param list 実際値
     */
    protected void assertBeanListEquals(String message, DataSet expected,
            List list) {

        BeanListReader reader = new BeanListReader(list);
        assertEquals(message, expected, reader.read());
    }

    /* (Javadoc なし)
     * @see junit.framework.TestCase#runBare()
     */
    public void runBare() throws Throwable {
        container_ = new S2ContainerImpl();
        setUp();
        try {
            setUpForEachTestMethod();
            try {
                container_.init();
                try {
                    setupDataSource();
                    try {
                        setUpAfterContainerInit();
                        bindFields();
                        try {
                            runTestTx();
                        } finally {
                            unbindFields();
                        }
                        tearDownBeforeContainerDestroy();
                    } finally {
                        tearDownDataSource();
                    }
                } finally {
                    container_.destroy();
                }
            } finally {
                tearDownForEachTestMethod();
            }

        } finally {
            tearDown();
        }
    }

    /**
     * <p>コンテナ初期化後に実行されるセットアップメソッドです。</p>
     * <p>必要な場合にオーバーライドしてください。</p>
     *
     * @throws Throwable
     */
    protected void setUpAfterContainerInit() throws Throwable {
    }

    /**
     * <p>setup() 後に実行されるテストメソッドごとのセットアップ
     * メソッドです。</p>
     * <p>testXxx() というメソッドの場合、setUpXxx() という名前で
     * セットアップメソッドを作成しておくと、自動的に実行されます。</p>
     *
     * @throws Throwable
     */
    protected void setUpForEachTestMethod() throws Throwable {
        invoke("setUp" + getTargetName());
    }

    /**
     * <p>コンテナ終了処理前に実行される終了処理メソッドです。</p>
     * <p>必要な場合にオーバーライドしてください。</p>
     *
     * @throws Throwable
     */
    protected void tearDownBeforeContainerDestroy() throws Throwable {
    }

    /**
     * <p>tearDown() 前に実行されるテストメソッドごとの終了処理メソッド
     * です。</p>
     * <p>testXxx() というメソッドの場合、tearDownXxx() という名前で
     * 終了処理メソッドを作成しておくと、自動的に実行されます。</p>
     *
     * @throws Throwable
     */
    protected void tearDownForEachTestMethod() throws Throwable {
        invoke("tearDown" + getTargetName());
    }

    private String getTargetName() {
        return getName().substring(4);
    }

    private void invoke(String methodName) throws Throwable {
        try {
            Method method = ClassUtil.getMethod(getClass(), methodName, null);
            MethodUtil.invoke(method, this, null);
        } catch (NoSuchMethodRuntimeException ignore) {
        }
    }

    private void bindFields() throws Throwable {
        bindedFields_ = new ArrayList();
        for (Class clazz = getClass(); clazz != S2TestCase.class
                && clazz != null; clazz = clazz.getSuperclass()) {

            Field[] fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; ++i) {
                bindField(fields[i]);
            }
        }
    }

    private void bindField(Field field) {
        if (isAutoBindable(field)) {
            field.setAccessible(true);
            if (FieldUtil.get(field, this) != null) {
                return;
            }
            String name = normalizeName(field.getName());
            Object component = null;
            if (getContainer().hasComponentDef(name)
                    && field.getType().isAssignableFrom(
                            getComponentDef(name).getComponentClass())) {
                component = getComponent(name);
            } else if (getContainer().hasComponentDef(field.getType())) {
                component = getComponent(field.getType());
            }
            if (component != null) {
                FieldUtil.set(field, this, component);
                bindedFields_.add(field);
            }
        }
    }

    private String normalizeName(String name) {
        return StringUtil.replace(name, "_", "");
    }

    private boolean isAutoBindable(Field field) {
        int modifiers = field.getModifiers();
        return !Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)
                && !field.getType().isPrimitive();
    }

    private void unbindFields() {
        for (int i = 0; i < bindedFields_.size(); ++i) {
            Field field = (Field) bindedFields_.get(i);
            try {
                field.set(this, null);
            } catch (IllegalArgumentException e) {
                System.err.println(e);
            } catch (IllegalAccessException e) {
                System.err.println(e);
            }
        }
    }

    private void runTestTx() throws Throwable {
        TransactionManager tm = null;
        if (needTransaction()) {
            try {
                tm = (TransactionManager) getComponent(TransactionManager.class);
                tm.begin();
            } catch (Throwable t) {
                System.err.println(t);
            }
        }
        try {
            runTest();
        } finally {
            if (tm != null) {
                tm.rollback();
            }
        }
    }

    private boolean needTransaction() {
        return getName().endsWith("Tx");
    }

    private void setupDataSource() {
        try {
            if (container_.hasComponentDef(DATASOURCE_NAME)) {
                dataSource_ = (DataSource) container_
                        .getComponent(DATASOURCE_NAME);
            } else if (container_.hasComponentDef(DataSource.class)) {
                dataSource_ = (DataSource) container_
                        .getComponent(DataSource.class);
            }
        } catch (Throwable t) {
            System.err.println(t);
        }
    }

    private void tearDownDataSource() {
        dbMetaData_ = null;
        if (connection_ != null) {
            ConnectionUtil.close(connection_);
            connection_ = null;
        }
        dataSource_ = null;
    }
}
EOF

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS