程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用Spring 2.5 TestContext測試框架

使用Spring 2.5 TestContext測試框架

編輯:關於JAVA

概述

Spring 2.5 相比於 Spring 2.0 所新增的最重要的功能可以歸結為以下 3 點:

基於注解的 IoC 功能;

基於注解驅動的 Spring MVC 功能;

基於注解的 TestContext 測試框架。

Spring 推薦開發者使用新的基於注解的 TestContext 測試框架,本文我們將對此進行詳細的講述。

低版本的 Spring 所提供的 Spring 測試框架構在 JUnit 3.8 基礎上擴展而來,它提供了若干個測試基類。而 Spring 2.5 所新增的基於注解的 TestContext 測試框架和低版本的測試框架沒有任何關系。它采用全新的注解技術可以讓 POJO 成為 Spring 的測試用例,除了擁有舊測試框架所有功能外,TestContext 還添加了一些新的功能,TestContext 可以運行在 JUnit 3.8、JUnit 4.4、TestNG 等測試框架下。

直接使用 JUnit 測試 Spring 程序存在的不足

在拙作《精通 Spring 2.x — 企業應用開發詳解》一書中,筆者曾經指出如果直接使用 JUnit 測試基於 Spring 的程序,將存在以下 4 點明顯的不足:

導致 Spring 容器多次初始化問題:根據 JUnit 測試用例的調用流程,每執行一個測試方法都會重新創建一個測試用例實例並調用其 setUp() 方法。由於在一般情況下,我們都在 setUp() 方法中初始化 Spring 容器,這意味著測試用例中有多少個測試方法,Spring 容器就會被重復初始化多少次。

需要使用硬編碼方式手工獲取 Bean:在測試用例中,我們需要通過 ApplicationContext.getBean() 的方法從 Spirng 容器中獲取需要測試的目標 Bean,並且還要進行造型操作。

數據庫現場容易遭受破壞:測試方法可能會對數據庫記錄進行更改操作,破壞數據庫現場。雖然是針對開發數據庫進行測試工作的,但如果數據操作的影響是持久的,將會形成積累效應並影響到測試用例的再次執行。舉個例子,假設在某個測試方法中往數據庫插入一條 ID 為 1 的 t_user 記錄,第一次運行不會有問題,第二次運行時,就會因為主鍵沖突而導致測試用例執行失敗。所以測試用例應該既能夠完成測試固件業務功能正確性的檢查,又能夠容易地在測試完成後恢復現場,做到踏雪無跡、雁過無痕。

不容易在同一事務下訪問數據庫以檢驗業務操作的正確性:當測試固件操作數據庫時,為了檢測數據操作的正確性,需要通過一種方便途徑在測試方法相同的事務環境下訪問數據庫,以檢查測試固件數據操作的執行效果。如果直接使用 JUnit 進行測試,我們很難完成這項操作。

Spring 測試框架是專門為測試基於 Spring 框架應用程序而設計的,它能夠讓測試用例非常方便地和 Spring 框架結合起來,以上所有問題都將迎刃而解。

一個需要測試的 Spring 服務類

在具體使用 TextContext 測試框架之前,我們先來認識一下需要測試的 UserService 服務類。UserService 服務類中擁有一個處理用戶登錄的服務方法,其代碼如下所示:

清單1. UserService.java 需要測試的服務類

package com.baobaotao.service;

import com.baobaotao.domain.LoginLog;
import com.baobaotao.domain.User;
import com.baobaotao.dao.UserDao;
import com.baobaotao.dao.LoginLogDao;

public class UserService{

   private UserDao userDao;
   private LoginLogDao loginLogDao;

   public void handleUserLogin(User user) {
     user.setCredits( 5 + user.getCredits());
     LoginLog loginLog = new LoginLog();
     loginLog.setUserId(user.getUserId());
     loginLog.setIp(user.getLastIp());
     loginLog.setLoginTime(user.getLastVisit());
     userDao.updateLoginInfo(user);
     loginLogDao.insertLoginLog(loginLog);
   }
   //省略get/setter方法
}

UserService 需要調用 DAO 層的 UserDao 和 LoginLogDao 以及 User 和 LoginLog 這兩個 PO 完成業務邏輯,User 和 LoginLog分別對應 t_user 和 t_login_log 這兩張數據庫表。

在用戶登錄成功後調用 UserService 中的 handleUserLogin() 方法執行用戶登錄成功後的業務邏輯:

登錄用戶添加 5 個積分(t_user.credits);

登錄用戶的最後訪問時間(t_user.last_visit)和 IP(t_user.last_ip)更新為當前值;

在日志表中(t_login_log)中為用戶添加一條登錄日志。

這是一個需要訪問數據庫並存在數據更改操作的業務方法,它工作在事務環境下。下面是裝配該服務類 Bean 的 Spring 配置文件:

清單2. applicationContext.xml:Spring 配置文件,放在類路徑下

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
   <!-- 配置數據源 -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
     p:driverClassName="com.mysql.jdbc.Driver"
     p:url="jdbc:mysql://localhost/sampledb"
     p:username="root"
     p:password="1234"/>

   <!-- 配置Jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
       p:dataSource-ref="dataSource"/>

   <!-- 配置dao -->
<bean id="loginLogDao"class="com.baobaotao.dao.LoginLogDao"
       p:jdbcTemplate-ref="jdbcTemplate"/>
<bean id="userDao" class="com.baobaotao.dao.UserDao"
p:jdbcTemplate-ref="jdbcTemplate"/>

<!-- 事務管理器 -->
<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
       p:dataSource-ref="dataSource"/>

<bean id="userService" class="com.baobaotao.service.UserService"
        p:userDao-ref="userDao" p:loginLogDao-ref="loginLogDao"/>

   <!-- 使用aop/tx命名空間配置事務管理,這裡對service包下的服務類方法提供事務-->
   <aop:config>
<aop:pointcut id="jdbcServiceMethod"
expression= "within(com.baobaotao.service..*)" />
<aop:advisor pointcut-ref="jdbcServiceMethod" advice-ref="jdbcTxAdvice" />
   </aop:config>
   <tx:advice id="jdbcTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
       <tx:method name="*"/>
     </tx:attributes>
</tx:advice>
</beans>

UserService 所關聯的 DAO 類和 PO 類都比較簡單,請參看本文附件的程序代碼。在著手測試 UserSerivce 之前,需要將創建數據庫表,你可以在附件的 schema 目錄下找到相應的 SQL 腳本文件。

編寫 UserService 的測試用例

下面我們為 UserService 編寫一個簡單的測試用例類,此時的目標是讓這個基於 TestContext 測試框架的測試類運行起來,我們將在後面逐步完善這個測試用例。

清單3.TestUserService.java: 基於注解的測試用例

package com.baobaotao.service;

import org.springframework.test.context.junit4.
   AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.Test;
import com.baobaotao.domain.User;

import java.util.Date;

@ContextConfiguration //①
public class TestUserService extends
   AbstractTransactionalJUnit4SpringContextTests {

@Autowired //②
   private UserService userService;

   @Test //③
   public void handleUserLogin(){
     User user = new User();
     user.setUserId(1);
     user.setLastIp("127.0.0.1");
     Date now = new Date();
     user.setLastVisit(now.getTime());
     userService.handleUserLogin(user);
   }
}

這裡,我們讓 TestUserService 直接繼承於 Spring 所提供的 AbstractTransactionalJUnit4SpringContextTests 的抽象測試類,稍後本文將對這個抽象測試類進行剖析,這裡你僅須知道該抽象測試類的作用是讓 TestContext 測試框架可以在 JUnit 4.4 測試框架基礎上運行起來就可以了。

在 ① 處,標注了一個類級的 @ContextConfiguration 注解,這裡 Spring 將按 TestContext 契約查找 classpath:/com/baobaotao/service/TestUserService-context.xml 的 Spring 配置文件,並使用該配置文件啟動 Spring 容器。@ContextConfiguration 注解有以下兩個常用的屬性:

locations:可以通過該屬性手工指定 Spring 配置文件所在的位置,可以指定一個或多個 Spring 配置文件。如下所示:

@ContextConfiguration(locations={“xx/yy/beans1.xml”,” xx/yy/beans2.xml”})

inheritLocations:是否要繼承父測試用例類中的 Spring 配置文件,默認為 true。如下面的例子:

@ContextConfiguration(locations={"base-context.xml"})
  public class BaseTest {
    // ...
  }
  @ContextConfiguration(locations={"extended-context.xml"})
  public class ExtendedTest extends BaseTest {
    // ...
  }

如果 inheritLocations 設置為 false,則 ExtendedTest 僅會使用 extended-context.xml 配置文件,否則將使用 base-context.xml 和 extended-context.xml 這兩個配置文件。

② 處的 @Autowired 注解讓 Spring 容器自動注入 UserService 類型的 Bean。而在 ③ 處標注的 @Test 注解則讓 handleUserLogin() 方法成為一個 JUnit 4.4 標准的測試方法, @Test 是 JUnit 4.4 所定義的注解。

在運行 TestUserService 測試類之前,讓我們先看一下 TestUserService-context.xml 配置文件的內容:

清單 4.TestUserService 所引用的 Spring 配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- ① 引入清單1定義的Spring配置文件 -->
<import resource="classpath:/applicationContext.xml"/>

</beans>

在 ① 處引入了清單 1 中定義的 Spring 配置文件,這樣我們就可以將其中定義的 UserService Bean 作為測試固件注入到 TestUserService 中了。

在你的 IDE 中(Eclipse、JBuilder、Idea 等),將 JUnit 4.4 類包引入到項目工程中後,在 TestUserService 類中點擊右鍵運行該測試類,將發現 TestUserService 已經可以成功運行了,如 圖 1 所示:

圖 1. 在 Eclipse 6.0 中運行 TestUserService

TestUserService 可以正確運行,說明其 userService 這個測試固件已經享受了 Spring 自動注入的功能。在運行該測試用例後,到數據庫中查看 t_user 表和 t_login_log 表,你會發現表數據和測試前是一樣的!這說明雖然我們在清單 3 的 handleUserLogin() 測試方法中執行了 userService.handleUserLogin(user) 的操作,但它並沒有對數據庫現場造成破壞:這是因為 Spring 的在測試方法返回前進行了事務回滾操作。

雖然 TestUserService.handleUserLogin() 測試方法已經可以成功運行,但是它在測試功能上是不完善的,讀者朋友可以已經發現了它存在以下兩個問題:

我們僅僅執行了 UserService#handleUserLogin(user) 方法,但驗證該方法執行結果的正確性。

在測試方法中直接使用 ID 為 1 的 User 對象進行測試,這相當於要求在數據庫 t_user 表必須已經存在 ID 為 1 的記錄,如果 t_user 中不存在這條記錄,將導致測試方法執行失敗。

准備測試數據並檢測運行結果

在這節裡,我們將著手解決上面所提出的兩個問題,在測試用例中准備測試數據並到數據庫中檢測業務執行結果的正確性。

准備測試數據

相比於在測試方法中直接訪問預定的數據記錄,在測試方法執行前通過程序准備一些測試數據,然後在此基礎上運行測試方法是比較好的策略,因為後者不需要對數據庫的狀態做假設。在 TestContext 中,你可以通過使用 JUnit 4.4 的 @Before 注解達到這個目的,請看下面的代碼:

清單5. 為測試方法准備數據

package com.baobaotao.service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;

import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.
AbstractTransactionalJUnit4SpringContextTests;

import com.baobaotao.dao.UserDao;
import com.baobaotao.domain.User;

@ContextConfiguration 
public class TestUserService
extends AbstractTransactionalJUnit4SpringContextTests {
   @Autowired
   private UserService userService;

   @Autowired
   private UserDao userDao;

   private int userId;

   @Before //① 准備測試數據
   public void prepareTestData() {
     final String sql = "insert into t_user(user_name,password) values('tom','1234')";
     simpleJdbcTemplate.update(sql);
     KeyHolder keyHolder = new GeneratedKeyHolder();
     simpleJdbcTemplate.getJdbcOperations().update( 
       new PreparedStatementCreator() {
         public PreparedStatement createPreparedStatement(Connection conn)
           throws SQLException {
           PreparedStatement ps = conn.prepareStatement(sql);
           return ps;
         }
       }, keyHolder);
     userId = keyHolder.getKey().intValue();//①-1 記錄測試數據的id
   }

   @Test
   public void handleUserLogin(){
     User user = userDao.getUserById(userId); //② 獲取測試數據
     user.setLastIp("127.0.0.1");
     Date now = new Date();
     user.setLastVisit(now.getTime());
     userService.handleUserLogin(user);
   }
}

JUnit 4.4 允許通過注解指定某些方法在測試方法執行前後進行調用,即是 @Before 和 @After 注解。在 Spring TestContext 中,標注 @Before 和 @After 的方法會在測試用例中每個測試方法運行前後執行,並和測試方法運行於同一個事務中。在 清單 5 中 ① 處,我們給 prepareTestData() 標注上了 @Before 注解,在該方法中准備一些測試數據,以供 TestUserService 中所有測試方法使用(這裡僅有一個 handleUserLogin() 測試方法)。由於測試方法運行後,整個事務會被回滾,在 prepareTestData() 中插入的測試數據也不會持久化到數據庫中,因此我們無須手工刪除這條記錄。

標注 @Before 或 @After 注解的方法和測試方法運行在同一個事務中,但有時我們希望在測試方法的事務開始之前或完成之後執行某些方法以便獲取數據庫現場的一些情況。這時,可以使用 Spring TestContext 的 @BeforeTransaction 和 @AfterTransaction 注解來達到目錄(這兩個注解位於 org.springframework.test.context.transaction 包中)。

雖然大多數業務方法都會訪問數據庫,但也並非所有需要測試的業務方法都需要和數據庫打交道。而在默認情況下,繼承於 AbstractTransactionalJUnit4SpringContextTests 測試用例的所有測試方法都將工作於事務環境下,你可以顯式地通過 @NotTransactional 注解,讓測試方法不工作於事務環境下。

prepareTestData() 方法中使用到了 simpleJdbcTemplate 對象訪問操作數據庫,該對象在 AbstractTransactionalJUnit4SpringContextTests 抽象類中定義,只要 Spring 容器有配置數據源,simpleJdbcTemplate 就會被自動創建。同時該抽象類中還擁有一個 Spring 容器引用:applicationContext,你可以借助該成員變量訪問 Spring 容器,執行獲取 Bean,發布事件等操作。

此外,AbstractTransactionalJUnit4SpringContextTests 還提供了若干個訪問數據庫的便捷方法,說明如下:

protected int countRowsInTable(String tableName) :計算數據表的記錄數。

protected int deleteFromTables(String... names):刪除表中的記錄,可以指定多張表。

protected void executeSqlScript(String sqlResourcePath, boolean continueOnError):執行 SQL 腳本文件,在腳本文件中,其格式必須一個 SQL 語句一行。

在測試方法 handleUserLogin() 的 ② 處,我們通過 userDao 獲取 prepareTestData() 添加的測試數據,測試方法在測試數據的基礎上執行業務邏輯。使用這種測試方式後,在任何情況下運行 TestUserService 都不會發生業務邏輯之外的問題。

檢驗業務邏輯的正確性

到目前為此,TestUserService 的 handleUserLogin() 測試方法僅是簡單地執行 UserService#handleUserLogin() 業務方法,但並沒有在業務方法執行後檢查執行結果的正確性,因此這個測試是不到位的。也就是說,我們必須訪問數據庫以檢查業務方法對數據更改是否成功:這包括積分(credits)、最後登錄時間(last_visit)、最後登錄 IP(last_ip)以及登錄日志表中的登錄日志記錄(t_login_log)。下面,我們補充這項重要的檢查數據正確性的工作:

清單5. 檢驗業務方法執行結果的正確性

@Test
public void handleUserLogin(){
   User user = userDao.getUserById(userId);
   user.setLastIp("127.0.0.1");
   Date now = new Date();
   user.setLastVisit(now.getTime());
   userService.handleUserLogin(user);

   //------------------以下為業務執行結果檢查的代碼---------------------
   User newUser = userDao.getUserById(userId);
   Assert.assertEquals(5, newUser.getCredits()); //①檢測積分
   //①檢測最後登錄時間和IP
   Assert.assertEquals(now.getTime(), newUser.getLastVisit());
   Assert.assertEquals("127.0.0.1",newUser.getLastIp());

   // ③檢測登錄記錄
   String sql = "select count(1) from t_login_log where user_id=? "+
     “ and login_datetime=? and ip=?";
   int logCount =simpleJdbcTemplate.queryForInt(sql, user.getUserId(),
     user.getLastVisit(),user.getLastIp());
   Assert.assertEquals(1, logCount);
   }

在業務方法執行後,我們查詢數據庫中相應記錄以檢查是否和期望的效果一致,如 ① 和 ② 所示。在 ③ 處,我們使用 SimpleJdbcTemplate 查詢 t_login_log,以檢查該表中是否已經添加了一條用戶登錄日志。

注意:由於我們的 DAO 層采用 Spring JDBC 框架,它沒有采用服務層緩存技術,所以可以使用 DAO 類返回數據庫中的數據。如果采用 Hibernate 等 ORM 框架,由於它們采用了服務層緩存的技術,為了獲取數據庫中的相應數據,需要在業務方法執行後調用 HibernateTemplate.flush() 方法,將緩存中的對象同步到數據庫中,這時才可以通過 SimpleJdbcTemplate 在數據庫中訪問業務方法的執行情況。

Spring TestContext 測試框架體系結構

在前面,我們直接通過擴展 AbstractTransactionalJUnit4SpringContextTests 編寫測試用例,在了解了編寫基於 TestContext 測試框架的測試用例後,現在是了解 TestContext 測試框架本身的時候了。

TestContext 核心類、支持類以及注解類

TestContext 測試框架的核心由 org.springframework.test.context 包中三個類組成,分別是 TestContext 和 TestContextManager 類以及 TestExecutionListener 接口。其類圖如下 圖 2 所示:

圖 2. Spring TestContext 測試框架核心類

TestContext:它封裝了運行測試用例的上下文;

TestContextManager:它是進入 Spring TestContext 框架的程序主入口,它管理著一個 TestContext 實例,並在適合的執行點上向所有注冊在 TestContextManager 中的 TestExecutionListener 監聽器發布事件:比如測試用例實例的准備,測試方法執行前後方法的調用等。

TestExecutionListener:該接口負責響應 TestContextManager 發布的事件。

Spring TestContext 允許在測試用例類中通過 @TestExecutionListeners 注解向 TestContextManager 注冊多個監聽器,如下所示:

@TestExecutionListeners( {
   DependencyInjectionTestExecutionListener.class,
   DirtiesContextTestExecutionListener.class })
public class TestXxxService{
   …
}

Spring 提供了幾個 TestExecutionListener 接口實現類,分別說明如下:

DependencyInjectionTestExecutionListener:該監聽器提供了自動注入的功能,它負責解析測試用例中 @Autowried 注解並完成自動注入;

DirtiesContextTestExecutionListener:一般情況下測試方法並不會對 Spring 容器上下文造成破壞(改變 Bean 的配置信息等),如果某個測試方法確實會破壞 Spring 容器上下文,你可以顯式地為該測試方法添加 @DirtiesContext 注解,以便 Spring TestContext 在測試該方法後刷新 Spring 容器的上下文,而 DirtiesContextTestExecutionListener 監聽器的工作就是解析 @DirtiesContext 注解;

TransactionalTestExecutionListener:它負責解析 @Transaction、@NotTransactional 以及 @Rollback 等事務注解的注解。@Transaction 注解讓測試方法工作於事務環境中,不過在測試方法返回前事務會被回滾。你可以使用 @Rollback(false) 讓測試方法返回前提交事務。而 @NotTransactional 注解則讓測試方法不工作於事務環境中。此外,你還可以使用類或方法級別的 @TransactionConfiguration 注解改變事務管理策略,如下所示: @TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
@Transactional 
public class TestUserService {
   …
}

我們知道在 JUnit 4.4 中可以通過 @RunWith 注解指定測試用例的運行器,Spring TestContext 框架提供了擴展於 org.junit.internal.runners.JUnit4ClassRunner 的 SpringJUnit4ClassRunner 運行器,它負責總裝 Spring TestContext 測試框架並將其統一到 JUnit 4.4 框架中。

TestContext 所提供的抽象測試用例

Spring TestContext 為基於 JUnit 4.4 測試框架提供了兩個抽象測試用例類,分別是 AbstractJUnit4SpringContextTests 和 AbstractTransactionalJUnit4SpringContextTests,而後者擴展於前者。讓我們來看一下這兩個抽象測試用例類的骨架代碼:

@RunWith(SpringJUnit4ClassRunner.class) //① 指定測試用例運行器 
@TestExecutionListeners(         //② 注冊了兩個TestExecutionListener監聽器 
   { DependencyInjectionTestExecutionListener.class,
   DirtiesContextTestExecutionListener.class })
public class AbstractJUnit4SpringContextTests implements ApplicationContextAware {
   …
}

① 處將 SpringJUnit4ClassRunner 指定為測試用例運行器,它負責無縫地將 TestContext 測試框架移花接木到 JUnit 4.4 測試框架中,它是 Spring TestContext 可以運行起來的根本所在。② 處通過 @TestExecutionListeners 注解向測試用例類中注冊了兩個 TestExecutionListener 監聽器,這兩個監聽器分別負責對 @Autowired 和 @DirtiesContext 注解進行處理,為測試用例提供自動注入和重新刷新 Spring 容器上下文的功能。

AbstractTransactionalJUnit4SpringContextTests 擴展於 AbstractJUnit4SpringContextTests,提供了事務管理的支持,其骨架代碼如下所示:

//① 注冊測試用例事務管理的監聽器 
@TestExecutionListeners( { TransactionalTestExecutionListener.class })
@Transactional  //② 使測試用例的所有方法都將工作於事務環境下
public class AbstractTransactionalJUnit4SpringContextTests
extends AbstractJUnit4SpringContextTests {
   …
}

在 ① 處,AbstractTransactionalJUnit4SpringContextTests 向測試用例類中注冊了 TransactionalTestExecutionListener 監聽器,這樣測試用例中的 @Transaction、@NotTransaction 以及 @Rollback 等注解就可以正確地工作起來了。注意,你不需要在 Spring 配置文件通過 <tx:annotation-driven /> 和 <context:annotation-config/> 為測試用例類啟用注解事務驅動和注解自動注入,這個工作完全於 TestContext 自身來解決(通過注冊 DependencyInjectionTestExecutionListener 和 TransactionalTestExecutionListener 監聽器),畢竟測試用例類沒有注冊到 Spring 容器中,沒有成為 Spring 的 Bean。

小結

我們通過對一個典型的涉及數據庫訪問操作的 UserService 服務類的測試,講述了使用 Spring 2.5 TestContext 測試框架進行集成測試的各項問題,這包括測試固件的自動注入、事務自動回滾、通過 SimpleJdbcTemplate 直接訪問數據庫以及測試數據准備等問題。

在通過一個實際例子的學習後,我們對如何使用 TestContext 測試框架有了一個具體的認識,在此基礎上我們對 Spring TestContext 測試框架體系結構進行了分析,然後剖析了 Spring 為 TestContext 嫁接到 JUnit 4.4 測試框架上所提供的兩個抽象測試用例類。

Spring 的 TestContext 測試框架不但可以整合到 JUnit 4.4 測試框架上,而且還可以整合到 JUnit 3.8 以及 TestNG 等測試框架上。目前已經提供了對 JUnit 3.8 以及 TestNG 的支持,你可以分別在 org.springframework.test.context.junit38 和 org.springframework.test.context.testng 包下找到整合的幫助類。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved