15. 集成測試

15. 集成測試

15.1 總覽

無需部署應用程序到服務器或連接到其他企業基礎架構即可執行一些集成測試,這一點非常重要。這將使開發者能夠測試以下內容:

  1. 正確織入Spring IoC容器上下文。
  2. 使用JDBC或ORM工具的數據訪問。例如,正確的sql語句、Hibernate的查詢、JPA的實體匹配等。

Spring框架在spring-test模塊中爲集成測試提供了優秀的支持。實際jar文件的名稱可能包含發行版本,也可能位於long org.springframework.test那張長長的表單中,具體取決於從哪兒獲取它(請參看“依賴管理”一節的解釋)。這個庫包含org.springframework.test包,它包含了用Spring容器進行集成測試的重要類。這些測試不依賴於應用程序服務器或其他環境部署。這些測試比單元測試運行速度要慢,但要比相同功能的Selenium測試或依賴部署到應用程序服務器的遠程測試快得多。
在Spring 2.5或更高版本中,單元測試和集成測試都支持以註解驅動的Spring TestContext框架(第15.5節)形式提供。TestContext框架不受實際使用的測試框架影響,因此能在各種環境中進行測試,包括JUnit、TestNG等等。

15.2 集成測試的目標

Spring的集成測試支持有以下的主要目標:

  1. 爲了管理在測試執行期間的Spring Ioc容器緩存(第15.2.1節)。
  2. 爲了提供依賴注入相關的測試工具實例(第15.2.2節)。
  3. 爲了提供用於集成測試的事務管理(第15.2.3節)。
  4. 爲了提供幫助開發人員編寫集成測試的,特定於Spring的基類(第15.2.4節)。

接下來的幾節將介紹每個目標,並提供實現和配置詳細信息的鏈接。

15.2.1 上下文管理和緩存

Spring TestContext框架提供了對Spring ApplicationContexts和WebApplicationContexts的相應加載以及這些上下文的緩存。對加載的上下文的緩存的支持非常重要,因爲啓動時間可能會成爲一個問題 – 不是因爲Spring本身的開銷,而是因爲Spring容器實例化的對象需要時間來實例化。例如,擁有50到100個Hibernate映射文件的項目可能需要10到20秒的時間才能加載映射文件,並且在每個測試中運行測試之前都必須承受該時間成本,這會降低整體測試的效率,從而降低開發者的工作效率。
測試類通常會爲XML或Groovy配置元數據集中聲明資源位置數組(通常位於類路徑)或用於配置應用程序的一組註解類。這些位置或類與用於生產部署的web.xml或其他指定的配置文件是類似的。
默認的情況下,ApplicationContext配置一旦加載即可在每個測試中重用。因此,每個測試套件只需承受一次設置成本,那麼隨後的測試執行速度就會快很多了。在這種情況下,術語“測試套件”意味着所有的測試都運行在同一個JVM中 - 例如,對於給定的項目或模塊,所有的測試都是從Ant、Maven或Gradle構建的。在不太可能的情況下, 測試會破壞應用程序上下文,並會需要重新加載 - 例如,修改bean定義或應用程序對象的狀態 - 可以配置TestContext框架用於重新加載配置並重建應用程序上下文,然後執行下一步測試。
參看第15.5.4 節“上下文管理”和第15.5.4.10 節“上下文緩存”瞭解測試上下文框架的更多內容。

15.2.2 測試工具的依賴注入

當使用TestContext框架加載應用程序上下文時,可以通過依賴注入有選擇性地配置測試類的實例。這爲在應用程序上下文使用預先配置的bean套件提供了方便機制。 這樣做的的優勢是:可以在各種測試場景(例如,配置Spring管理的對象、事務代理、數據源等)中重複使用應用程序上下文,從而避免爲單個測試用例重複配置複雜的測試設置。
舉個例子:假設有HibernateTitleRepository類,它實現了Title字段實體的數據訪問邏輯。現在需要編寫包含以下內容的集成測試:

  1. Spring配置:所有與HibernateTitleRepository bean相關的配置是否正確表達?
  2. Hibernate映射文件配置:是否正確映射了所有內容,是否正確配置了lazy-loading?
  3. HibernateTitleRepository的邏輯:此類的配置實例是否預期執行?

更多,請參看TestContext框架對測試裝置的依賴注入(第15.5.5節)。

15.2.3 事務管理

訪問真實數據庫進行測試時,有一個常見的問題就是測試可能影響持久性數據的狀態。即使是使用開發數據庫,對狀態的更改也可能影響將來的測試。另外,許多操作 - 例如插入或修改持久數據 - 不能在事務之外執行(或驗證)。
TestContext框架解決了這個問題。默認情況下, 框架會創建並回滾每個測試的事務。開發者只需編寫可以帶事務的代碼。如果在測試中調用事務代理對象,那麼將會根據這個配置的事務性語義作出正確的行爲。此外,如果測試方法在爲測試管理的事務內運行時刪除所選表的內容時,該事務在默認情況下會回滾,並且數據庫將在執行測試之前返回到原來的狀態。事務性支持通過在測試的應用程序上下文中定義的PlatformTransactionManager bean提供。
如果開發者希望事務被提交? - 即有一個特殊的測試希望可以新增或修改數據庫 - 那麼可以配置TestContext框架將事務提交,而不執行@commit回滾。
更多參看第15.5.7節,使用TestContext框架的事務管理。

15.2.4 支持集成測試的類

Spring TestContext框架提供一些抽象支持類,可以簡化集成測試的代碼編程。這些基本測試類爲測試框架和便捷的實例變量和方法提供了良好定義的鉤子,開發者能用於:

  1. ApplicationContext用於執行顯式的bean查找或測試整個上下文狀態。
  2. 提供用於執行SQL語句來查詢數據庫的JdbcTemplate。 在執行數據庫相關的應用程序代碼之前和之後,可以使用這種查詢來確認數據庫狀態,Spring確保這些查詢在與應用程序代碼相同的事務範圍內運行。當與ORM工具一起使用時,一定要避免誤報。

另外,開發者可能需要創建自定義的,能應用在整個程序範圍的超類,包含特定於項目的實例變量和方法。參看第15.5.9節,用於TestContext框架的支持類。

15.3 JDBC測試支持

org.springframework.test.jdbc包包含JdbcTestUtils類,它是jdbc相關的實用工具的集合,目的是簡化標準數據庫測試方案。具體地說,JdbcTestUtils提供了以下靜態實用工具方法。

  1. countRowsInTable(…):計算給定表的行數;
  2. countRowsInTableWhere (…):使用提供的where子句計算給定表中的行數;
  3. deleteFromTables(…):刪除指定表的所有行;
  4. deleteFromTableWhere(…):使用提供的where子句從給定表中刪除行;
  5. dropTables(…):徹底刪除指定的表。

請注意,AbstractTransactionalJUnit4SpringContextTestsAbstractTransactionalTestNGSpringContextTests提供了在JdbcTestUtils中委託給上述方法的便利方法。

spring-jdbc模塊提供了對配置和啓動嵌入式數據庫的支持,可用於與數據庫交互的集成測試。有關詳細信息,請參見地19.8節“嵌入數據庫的支持”和第19.8.5節“使用嵌入數據庫測試數據訪問的邏輯”。

15.4 註解

15.4.1 Spring測試註解

Spring框架提供了以下一組特定於Spring的註解,能讓開發者在單元和集成測試中使用TestContext框架。有關的詳細信息(包括默認屬性值、屬性別名等),請參看相應的javadocs。

15.4.1.1 @BootstrapWith註解

@BootstrapWith是一個類級註解,用於配置Spring TestContext框架的引導。具體地說, @BootstrapWith用於指定自定義的TestContextBootstrapper。有關詳細信息,請參看第15.5.2節“TestContext的引導”。

15.4.1.2 @ContextConfiguration註解

@ContextConfiguration定義類級元數據,用於確定如何爲集成測試加載和配置ApplicationContext。具體地說,@ContextConfiguration聲明應用程序上下文的資源位置和用於加載上下文中帶註解的類。

資源位置通常是XML配置文件或者是在類路徑中的Groovy腳本;註解類通常是@Configuration類。但是,資源位置也可以引用文件系統中的文件和腳本,而帶註解的類可以是組件(component )類等等。

@ContextConfiguration("/test-config.xml")
public class XmlApplicationContextTests {
// class body...
}
 
@ContextConfiguration(classes = TestConfig.class)
public class ConfigClassApplicationContextTests {
// class body...
}

除了聲明資源位置或註解類之外,還可以使用@ContextConfiguration來聲明ApplicationContextInitializer類。

@ContextConfiguration(initializers =CustomContextIntializer.class)
public class ContextInitializerTests {
// class body...
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章