基於事務處理的測試類

一、Spring提供的JUnit框架擴展:

1.AbstractSpringContextTests:spring中使用spring上下文測試的Junit擴展類,我們一般不會使用這個類來進行單元測試,它是spring內部設計使用到的類
2.AbstractDependencyInjectionSpringContextTests:這是AbstractSpringContextTests的直接子類,支持依賴spring上下文的測試類,這個類不支持事務。
3.AbstractTransactionalSpringContextTests:這是 AbstractDependencyInjectionSpringContextTests的直接子類,這個類一般應用在事務相關的測試中,一旦完成每個測試它就會正常地回滾事務,不會真正更新數據庫,若要手動設置事務相關操作,你可以重載onSetUpInTransaction和 onTearDownInTransaction方法,以便手工開始並提交事務,或者調用setComplete()方法。這個類也可以在沒有事務的情況下,使用這個類。
4.AbstractTransactionalDataSourceSpringContextTests:這是 AbstractTransactionalSpringContextTests的直接子類,它使用了Spring的基於JDBC的 jdbcTemplate工具類,支持數據庫級別的事務。

package com.hsaction.framework.core.test.support;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

/**
 * <p>Title:基於事務處理的測試類</p>
 * <p>Description:爲測試提供了一個自動回滾的測試機制。當基於本類測試時,每個測試用例的操作在測試完畢後均被回滾。</p>
 * <p>Copyright: Copyright (c) 2007 邢修義 (Hubert Star)</p>
 * <p>Company: HS Action Computer Tech. Studio</p>
 * @author 邢修義
 * <p>Datetime 2007-3-24 上午01:38:41</p>
 */

/* -------------------------修訂記錄--------------------------------
 * 1.
 *    修改原因:
 *    修改內容:
 *    修改時間:
 *    修改人員:
 * ---------------------------------------------------------------
 */

public abstract class AbstractTransactionalSpringContextNGTestCase extends AbstractNGTestCase {
    /**
     * Logger for this class
     */
    private static final Log logger = LogFactory.getLog(AbstractTransactionalSpringContextNGTestCase.class);

    protected PlatformTransactionManager transactionManager;

    private boolean defaultRollback = true;

    private boolean complete = false;

    private int transactionsStarted = 0;

    protected TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();

    protected TransactionStatus transactionStatus;

    /**
     * 默認的構造方法
     */
    public AbstractTransactionalSpringContextNGTestCase() {
        super();
    }

    /**
     * 事務之前的處理,子類必須實現此方法
     * @throws Exception
     */
    protected abstract void onSetUpBeforeTransaction() throws Exception;

    /**
     * 事務清理之後的處理,子類必須實現此方法
     * @throws Exception
     */
    protected abstract void onTearDownAfterTransaction() throws Exception;

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void setDefaultRollback(boolean defaultRollback) {
        this.defaultRollback = defaultRollback;
    }

    protected void preventTransaction() {
        this.transactionDefinition = null;
    }

    protected void setTransactionDefinition(TransactionDefinition customDefinition) {
        this.transactionDefinition = customDefinition;
    }

    /**
     * 開始事務過程之中的處理方法,可以選擇實現
     * @throws Exception
     */
    protected void onSetUpInTransaction() throws Exception {
    }

    /**
     * 結束事務過程之中的處理方法,可以選擇實現
     * @throws Exception
     */
    protected void onTearDownInTransaction() throws Exception {
    }

    /**
     * 實現基類中的方法前準備工作,此處開始一個新事務
     * @throws Exception
     */
    protected final void onSetup() throws Exception {
        this.complete = !this.defaultRollback;

        if (this.transactionManager == null) {
            logger.info("No transaction manager set: test will NOT run within a transaction");
        } else if (this.transactionDefinition == null) {
            logger.info("No transaction definition set: test will NOT run within a transaction");
        } else {
            this.onSetUpBeforeTransaction();
            this.startNewTransaction();
            try {
                this.onSetUpInTransaction();
            } catch (Exception ex) {
                this.endTransaction();
                throw ex;
            }
        }
    }

    /**
     * 實現基類中的方法執行後清理工作,此處結束事務
     * @throws Exception
     */
    protected final void onTearDown() throws Exception {
        if (this.transactionStatus != null && !this.transactionStatus.isCompleted()) {
            try {
                this.onTearDownInTransaction();
            } finally {
                this.endTransaction();
            }
        }
        if (this.transactionsStarted > 0) {
            this.onTearDownAfterTransaction();
        }
    }

    /**
     * 設置執行行爲爲測試後提交事務,默認事務是測試完畢馬上回滾的
     *
     */
    protected void setComplete() {
        if (this.transactionManager == null) {
            throw new IllegalStateException("No transaction manager set");
        }
        this.complete = true;
    }

    /**
     * 開始事務
     * @throws TransactionException
     */
    protected void startNewTransaction() throws TransactionException {
        if (this.transactionStatus != null) {
            throw new IllegalStateException("Cannot start new transaction without ending existing transaction: " + "Invoke endTransaction() before startNewTransaction()");
        }
        if (this.transactionManager == null) {
            throw new IllegalStateException("No transaction manager set");
        }

        this.transactionStatus = this.transactionManager.getTransaction(this.transactionDefinition);
        ++this.transactionsStarted;
        this.complete = !this.defaultRollback;

        if (logger.isInfoEnabled()) {
            logger.info("Began transaction (" + this.transactionsStarted + "): transaction manager [" + this.transactionManager + "]; default rollback = " + this.defaultRollback);
        }
    }

    /**
     * 結束事務,根據complete決定提交或者回滾事務
     *
     */
    protected void endTransaction() {
        if (this.transactionStatus != null) {
            try {
                if (!this.complete) {
                    this.transactionManager.rollback(this.transactionStatus);
                    logger.info("Rolled back transaction after test execution");
                } else {
                    this.transactionManager.commit(this.transactionStatus);
                    logger.info("Committed transaction after test execution");
                }
            } finally {
                this.transactionStatus = null;
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章