溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring集成測試方法是什么

發(fā)布時(shí)間:2021-12-22 11:59:05 來源:億速云 閱讀:89 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“Spring集成測試方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Spring集成測試方法是什么”吧!

3.1 概要

能夠執(zhí)行一些集成測試而無需部署到應(yīng)用程序服務(wù)器或連接到其他企業(yè)基礎(chǔ)結(jié)構(gòu),這一點(diǎn)很重要。這樣可以測試以下內(nèi)容:

  • 正確連接Spring IoC容器上下文。

  • 使用JDBC或ORM工具進(jìn)行數(shù)據(jù)訪問。這可以包括諸如SQL語句的正確性、Hibernate查詢、JPA實(shí)體映射之類的東西。

Spring框架為Spring測試模塊中的集成測試提供了一流的支持。實(shí)際的JAR文件的名稱可能包括發(fā)行版,也可能采用長org.springframework.test格式,具體取決于你從何處獲?。ㄕ垍㈤啞耙蕾嚬芾怼辈糠种械恼f明)。該庫包含org.springframework.test包,其中包含用于與Spring容器進(jìn)行集成測試的有價(jià)值的類。此測試不依賴于應(yīng)用程序服務(wù)器或其他部署環(huán)境。此類測試的運(yùn)行速度比單元測試慢,但比依賴于部署到應(yīng)用程序服務(wù)器的等效Selenium測試或遠(yuǎn)程測試快。

單元和集成測試支持以注解驅(qū)動(dòng)的Spring TestContext 框架的形式提供。TestContext框架與實(shí)際使用的測試框架無關(guān),該框架允許各種環(huán)境(包括JUnit,TestNG和其他環(huán)境)中對測試進(jìn)行檢測。

3.2 集成測試目標(biāo)

Spring的集成測試支持的主要目標(biāo)如下:

  • 在測試之間管理Spring IoC容器緩存。

  • 提供測試fixture實(shí)例的依賴注入。

  • 提供適合集成測試的事務(wù)管理。

  • 提供特定于Spring的基類,以幫助開發(fā)人員編寫集成測試

接下來的幾節(jié)描述了每個(gè)目標(biāo),并提供了有關(guān)實(shí)現(xiàn)和配制詳細(xì)信息的鏈接。

Fixture意思:JUnit提供了編寫測試前準(zhǔn)備、測試后清理的固定代碼,我們稱之為Fixture

3.2.1 上下文管理和緩存

Spring TestContext 框架提供了Spring ApplicationContext實(shí)例和WebApplicationContext實(shí)例的一致加載以及這些上下文的緩存。支持加載上下文的緩存很重要,因?yàn)閱?dòng)時(shí)間可能會(huì)成為一個(gè)問題-不是因?yàn)镾pring本身的開銷,而是因?yàn)镾pring容器實(shí)例化的對象需要時(shí)間才能實(shí)例化。例如,具有50到100個(gè)Hibernate映射文件的項(xiàng)目可能需要10到20秒來加載映射文件,并且在每個(gè)測試fixture中運(yùn)行每個(gè)測試之前要承擔(dān)該消耗,這會(huì)導(dǎo)致整體測試運(yùn)行速度變慢,從而降低了開發(fā)人員的工作效率。

測試類通常聲明XML或Groovy配置元數(shù)據(jù)的資源位置數(shù)組(通常是在類路徑中)或用于配置應(yīng)用程序的組件類的數(shù)組。這些位置或類與web.xml或其他用于生產(chǎn)部署的配置文件中指定的位置或類相同或相似。

默認(rèn)情況下,加載后,已配置的ApplicationContext將重新用每個(gè)測試。因此,每個(gè)測試套件僅產(chǎn)生一次安裝成本,并且隨后的測試執(zhí)行要快得多。在這種情況下,術(shù)語“測試套件”是指所有測試都在相同JVM中運(yùn)行,例如,所有測試都從給定項(xiàng)目或模塊的AntMavenGradle構(gòu)建運(yùn)行。在不太可能的情況下,測試破壞了應(yīng)用程序上下文并需要重新加載(例如,通過修改bean定義或應(yīng)用程序?qū)ο蟮臓顟B(tài)),可以將TestContext框架配置為重新加載配置并重建應(yīng)用程序上下文,然后再執(zhí)行下一個(gè)測試。

請參見使用TestContext框架進(jìn)行上下文管理和上下文緩存。

3.2.2 測試裝置的依賴注入

當(dāng)TestContext框架加載你的應(yīng)用程序上下文時(shí),可以選擇地用依賴注入來配置測試類的實(shí)例。這提供了一種方便的機(jī)制,可以通過在應(yīng)用程序上下文中使用預(yù)配置的bean來設(shè)置測試fixture。這里一個(gè)強(qiáng)大的好處是,你可以跨各種測試場景重用應(yīng)用程序上下文(例如,用于配置spring管理的對象圖、事務(wù)代理、數(shù)據(jù)源實(shí)例等),從而避免為單個(gè)測試用例重復(fù)復(fù)雜的測試fixture設(shè)置。

例如,考慮一個(gè)場景,其中我們有一個(gè)類(HibernateTitleRepository),該類為Title域?qū)嶓w實(shí)現(xiàn)數(shù)據(jù)訪問邏輯。我們要編寫集成測試來測試以下方面:

  • Spring配置:基本上,與HibernateTitleRepository bean的配置有關(guān)的一切都正確并存在嗎?

  • Hibernate映射文件配置:是否已正確映射所有內(nèi)容,并且是否有正確的延遲加載配置?

  • HibernateTitleRepository的邏輯:此類的配置實(shí)例是否按預(yù)期執(zhí)行?

3.2.3 事物管理

訪問真實(shí)數(shù)據(jù)庫的測試中的一個(gè)常見問題是它們對持久存儲狀態(tài)的影響。即使使用開發(fā)數(shù)據(jù)庫,對狀態(tài)的更改也可能會(huì)影響以后的測試。同樣,許多操作(例如插入或修改持久數(shù)據(jù))無法在事物之外執(zhí)行(或驗(yàn)證)。

TestContext框架解決了這個(gè)問題。默認(rèn)情況下,框架為每個(gè)測試創(chuàng)建并回滾事務(wù)。你可以編寫可以假定存在事務(wù)的代碼。如果在測試中調(diào)用事務(wù)代理對象,則對象將根據(jù)其配置事務(wù)語義正確運(yùn)行。此外,如果測試方法在測試管理的事務(wù)中運(yùn)行時(shí)刪除了選定表的內(nèi)容,則該事務(wù)將默認(rèn)回滾,并且數(shù)據(jù)庫將返回到執(zhí)行測試之前的狀態(tài)。通過使用在測試的應(yīng)用程序上下文中定義的PlatformTransactionManager bean,可以為測試提供事務(wù)支持。

如果你想要提交一個(gè)事務(wù)(不常見,但是當(dāng)你想要一個(gè)特定的測試填充或修改數(shù)據(jù)庫時(shí),偶爾會(huì)有用),你可以通過使用@Commit注解告訴TestContext框架使事務(wù)提交而不是回滾。

請參閱使用TestContext框架進(jìn)行事務(wù)管理。

3.2.4 集成測試支持的類

Spring TestContext框架提供了幾個(gè)抽象支持類,這些基礎(chǔ)測試類為測試框架提供了定義明確的鉤子,以方便的實(shí)例變量和方法,可用于訪問以下內(nèi)容:

  • ApplicationContext,用于執(zhí)行顯式的bean查找或測試整個(gè)上下文的狀態(tài)。

  • 一個(gè)JdbcTemplate,用于執(zhí)行SQL語句來查詢數(shù)據(jù)庫。你可以使用此類查詢在執(zhí)行與數(shù)據(jù)庫相關(guān)的應(yīng)用程序代碼之前和之后確認(rèn)數(shù)據(jù)庫狀態(tài),并且Spring確保此類查詢在與應(yīng)用程序代碼相同的事務(wù)范圍內(nèi)運(yùn)行。與ORM工具一起使用時(shí),請確保避免誤報(bào)。

另外,你可能希望使用針對你的項(xiàng)目的實(shí)例變量和方法構(gòu)建自己的自定義,應(yīng)用程序范圍的超類。

請參閱TestContext框架的支持類。

3.3 JDBC測試支持

org.springframework.test.jdbc包包含JdbcTestUtils,它是JDBC相關(guān)實(shí)用程序功能的集合,旨在簡化標(biāo)準(zhǔn)數(shù)據(jù)庫測試方案。具體來說,JdbcTestUtils提供以下靜態(tài)實(shí)用程序方法。

  • countRowsInTable(..):計(jì)算給定表中的行數(shù)。

  • countRowsInTableWhere(..):使用提供的WHERE子句計(jì)算給定表中的行數(shù)。

  • deleteFromTables(..):刪除指定表中的所有行。

  • deleteFromTableWhere(..): 使用提供的WHERE子句從給定表中刪除行。

AbstractTransactionalJUnit4SpringContextTestsAbstractTransactionalTestNGSpringContextTests提供了便利的方法,這些方法委托給JdbcTestUtils中的上述方法。spring-jdbc模塊提供了對配置和啟動(dòng)嵌入式數(shù)據(jù)庫的支持你可以在與數(shù)據(jù)庫交互的集成測試中使用它。有關(guān)詳細(xì)信息,請參見嵌入式數(shù)據(jù)庫支持和使用嵌入式數(shù)據(jù)庫測試數(shù)據(jù)訪問邏輯。

3.4 注解

本節(jié)介紹了在測試Spring應(yīng)用程序時(shí)可以使用的注解。它包括以下主題:

  • Spring測試注解

  • 標(biāo)準(zhǔn)注解支持

  • Spring JUnit4測試注解

  • Spring JUnit Jupiter測試注解

  • 測試元注解支持

3.4.1 Spring測試注解

Spring框架提供了以下特定于Spring的注解集,你可以在單元測試和集成測試中將它們與TestContext框架結(jié)合使用。有關(guān)更多信息,請參見相應(yīng)的javadoc,包括默認(rèn)屬性值、屬性別名和其他詳細(xì)信息。

Spring的測試注解包括以下內(nèi)容:

  • @BootstrapWith

  • @ContextConfiguration

  • @WebAppConfiguration

  • @ContextHierarchy

  • @ActiveProfiles

  • @TestPropertySource

  • @DynamicPropertySource

  • @DirtiesContext

  • @TestExecutionListeners

  • @Commit

  • @Rollback

  • @BeforeTransaction

  • @AfterTransaction

  • @Sql

  • @SqlConfig

  • @SqlMergeMode

  • @SqlGroup

@BootstrapWith

@BootstrapWith是一個(gè)類級別的注解,可用于配置如何引導(dǎo)Spring TestContext 框架。具體來說,你可以使用@BootstrapWith指定自定義TestContextBootstrapper。有關(guān)更多詳細(xì)信息,請參見有關(guān)引導(dǎo)TestContext框架的部分。


@ContextConfiguration

@ContextConfiguration定義了用于確定如何為集成測試加載和配置ApplicationContext的類級元數(shù)據(jù)。具體來說,@ContextConfiguration聲明應(yīng)用程序上下文資源位置或用于加載上下文的組件類。

資源位置通常是位于類路徑中的XML配置文件或Groovy腳本,而組件類通常是@Configuration類。但是,資源位置也可以引用文件系統(tǒng)中的文件和腳本,組件類可以是@Component類、@Service類等等。有關(guān)更多詳細(xì)信息,請參見組件類。

以下示例顯示了一個(gè)指向XML文件的@ContextConfiguration注解:

@ContextConfiguration("/test-config.xml") //
class XmlApplicationContextTests {
    // class body...
}
  1. 引用XML文件。

以下示例顯示了一個(gè)@ContextConfiguration注解,該注解引用了一個(gè)類:

@ContextConfiguration(classes = TestConfig.class) //1
class ConfigClassApplicationContextTests {
    // class body...
}
  1. 引用類文件


作為聲明資源位置或組件類的替代方法或補(bǔ)充,可以使用@ContextConfiguration聲明ApplicationContextInitializer類。以下示例顯示了這種情況:

@ContextConfiguration(initializers = CustomContextIntializer.class) 
class ContextInitializerTests {
    // class body...
}


你可以選擇使用@ContextConfiguration來聲明ContextLoader策略。但是,你通常不需要顯式配置加載器,因?yàn)槟J(rèn)加載器支持初始化程序以及資源位置或組件類。

以下示例同時(shí)使用配置位置和加載器:

@ContextConfiguration(locations = "/test-context.xml", loader = CustomContextLoader.class) //1
class CustomLoaderXmlApplicationContextTests {
    // class body...
}
  1. 配置位置和自定義加載器。

@ContextConfiguration為繼承資源位置或配置類以及超類聲明上下文初始化器提供支持。

@WebAppConfiguration

@WebAppConfiguration是一個(gè)類級別的注解,可用于聲明為集成測試加載的ApplicationContext應(yīng)該是WebApplicationContext@WebAppConfiguration僅存在于測試類上,可以確保為測試加@WebApplicationContext,并使用默認(rèn)值file:src/main/webapp作為Web應(yīng)用程序根目錄(也就是即資源基本路徑)。資源基礎(chǔ)路徑用于在后臺創(chuàng)建MockServletContext,該MockServletContext用作測試的WebApplicationContextServletContext

以下示例顯示了如何使用@WebAppConfiguration注解:

@ContextConfiguration
@WebAppConfiguration //
class WebAppTests {
    // class body...
}

要覆蓋默認(rèn)值,可以使用隱式值屬性指定其他基礎(chǔ)資源路徑。classpath:file:資源前綴均受支持。如果未提供資源前綴,則假定該路徑是文件系統(tǒng)資源。以下示例顯示如何指定類路徑資源:

@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources") //1
class WebAppTests {
    // class body...
}
  1. 指定類路徑資源。

注意,@WebAppConfiguration必須與@ContextConfiguration一起使用,可以在單個(gè)測試類中使用,也可以在測試類層次結(jié)構(gòu)中使用。

@ContextHierarchy

@ContextHierarchy是一個(gè)類級注解,用于定義集成測試的ApplicationContext實(shí)例的層次結(jié)構(gòu)。 @ContextHierarchy應(yīng)該用一個(gè)或多個(gè)@ContextConfiguration實(shí)例的列表聲明,每個(gè)實(shí)例定義上下文層次結(jié)構(gòu)中的一個(gè)級別。以下示例演示了在單個(gè)測試類中使用@ContextHierarchy(也可以在測試類層次結(jié)構(gòu)中使用@ContextHierarchy):

@ContextHierarchy({
    @ContextConfiguration("/parent-config.xml"),
    @ContextConfiguration("/child-config.xml")
})
class ContextHierarchyTests {
    // class body...
}
@WebAppConfiguration
@ContextHierarchy({
    @ContextConfiguration(classes = AppConfig.class),
    @ContextConfiguration(classes = WebConfig.class)
})
class WebIntegrationTests {
    // class body...
}

如果需要合并或覆蓋測試類層次結(jié)構(gòu)中上下文層次結(jié)構(gòu)的給定級別的配置,則必須通過在類層次結(jié)構(gòu)的每個(gè)對應(yīng)級別上為@ContextConfiguration中的name屬性提供相同的值來顯式地命名該級別。有關(guān)更多示例,請參見上下文層次結(jié)構(gòu)和@ContextHierarchy javadoc。

@ActiveProfiles

@ActiveProfiles是一個(gè)類級別的注解,用于聲明在為集成測時(shí)加載ApplicationContext時(shí)應(yīng)啟用哪些bean定義配置文件。

以下示例表明dev配置文件應(yīng)處于活動(dòng)狀態(tài):

@ContextConfiguration
@ActiveProfiles("dev") //1
class DeveloperTests {
    // class body...
}
  1. 指示開發(fā)配置文件應(yīng)處于活動(dòng)狀態(tài)。

以下示例表明devintegration配置文件均應(yīng)處于活動(dòng)狀態(tài):

@ContextConfiguration
@ActiveProfiles({"dev", "integration"}) //1
class DeveloperIntegrationTests {
    // class body...
}
  1. 指示devintegration配置文件應(yīng)該處于活動(dòng)狀態(tài)。

@ActiveProfiles提供了對繼承默認(rèn)情況下超類聲明的活動(dòng)bean定義配置文件的支持。你還可以通過實(shí)現(xiàn)自定義ActiveProfilesResolver并使用@ActiveProfilesresolver屬性對其進(jìn)行注冊,以編程方式解析活動(dòng)bean定義配置文件。

@TestPropertySource

@TestPropertySource是類級別的注解,可用于配置屬性文件和內(nèi)聯(lián)屬性的位置,這些屬性和內(nèi)聯(lián)屬性將被添加到環(huán)境中針對集成測試加載的ApplicationContextPropertySources集中。

下面的示例演示如何從類路徑聲明屬性文件:

@ContextConfiguration
@TestPropertySource("/test.properties") //1
class MyIntegrationTests {
    // class body...
}
  1. 從類路徑根目錄中的test.properties獲取屬性。

下面的示例演示如何聲明內(nèi)聯(lián)屬性:

@ContextConfiguration
@TestPropertySource(properties = { "timezone = GMT", "port: 4242" }) //1
class MyIntegrationTests {
    // class body...
}
  1. 聲明時(shí)區(qū)和端口屬性。

有關(guān)示例和更多詳細(xì)信息,請參見使用測試屬性源進(jìn)行上下文配置。

@DynamicPropertySource

@DynamicPropertySource是方法級別的注解,可用于注冊動(dòng)態(tài)屬性,以將動(dòng)態(tài)屬性添加到環(huán)境中針對集成測試加載的ApplicationContextPropertySources集中。當(dāng)你不預(yù)先知道屬性的值時(shí),例如,如果屬性是由外部資源管理的,例如由Testcontainers項(xiàng)目管理的容器,則動(dòng)態(tài)屬性很有用。

下面的示例演示如何注冊動(dòng)態(tài)屬性:

@ContextConfiguration
class MyIntegrationTests {

    static MyExternalServer server = // ...

    @DynamicPropertySource //1
    static void dynamicProperties(DynamicPropertyRegistry registry) { //2
        registry.add("server.port", server::getPort); //3
    }

    // tests ...
}
  1. 使用@DynamicPropertySource注解靜態(tài)方法。

  2. 接受DynamicPropertyRegistry作為參數(shù)。

  3. 注冊要從服務(wù)器延遲檢索的動(dòng)態(tài)server.port屬性。

@DirtiesContext

@DirtiesContext表示底層的Spring ApplicationContext在執(zhí)行測試期間已被清理(即,該測試以某種方式修改或破壞了它(例如,通過更改單例bean的狀態(tài))),應(yīng)將其關(guān)閉。當(dāng)應(yīng)用程序上下文被標(biāo)記為清理時(shí),它將從測試框架的緩存中刪除并關(guān)閉。因此,對于需要具有相同配置元數(shù)據(jù)的上下文的后續(xù)測試,將重新構(gòu)建底層Spring容器。

你可以將@DirtiesContext用作同一類或類層次結(jié)構(gòu)中的類級別和方法級別的注解。在這種情況下,取決于配置的methodModeclassMode,在任何此類帶注解的方法之前或之后以及當(dāng)前測試類之前或之后,ApplicationContext均標(biāo)記為清理。

以下示例說明了在各種配置情況下何時(shí)清理上下文:

  • 在當(dāng)前測試類之前,在類模式設(shè)置為BEFORE_CLASS的類上聲明時(shí)。

    @DirtiesContext(classMode = BEFORE_CLASS) //1
    class FreshContextTests {
        // some tests that require a new Spring container
    }

     

    1. 在當(dāng)前測試類之前清理上下文。

  • 在當(dāng)前測試類之后,當(dāng)在類模式設(shè)置為AFTER_CLASS(即默認(rèn)類模式)的類上聲明時(shí)。

    @DirtiesContext 
    class ContextDirtyingTests {
        // some tests that result in the Spring container being dirtied
    }

     

    1. 當(dāng)前測試類之后清理上下文。

  • 在當(dāng)前測試類中的每個(gè)測試方法之后,在類模式設(shè)置為AFTER_EACH_TEST_METHOD的類上聲明時(shí)。

    @DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) 
    class ContextDirtyingTests {
        // some tests that result in the Spring container being dirtied
    }

     

    1. 每種測試方法后清理上下文。

  • 在當(dāng)前測試之前,當(dāng)在方法模式設(shè)置為BEFORE_METHOD的方法上聲明時(shí)。

    @DirtiesContext(methodMode = BEFORE_METHOD) //1
    @Test
    void testProcessWhichRequiresFreshAppCtx() {
        // some logic that requires a new Spring container
    }

     

    1. 在當(dāng)前測試方法之前清理上下文。

  • 當(dāng)前測試之后,當(dāng)在方法模式設(shè)置為AFTER_METHOD的方法上聲明時(shí)(即默認(rèn)方法模式)。

    @DirtiesContext //1
    @Test
    void testProcessWhichDirtiesAppCtx() {
        // some logic that results in the Spring container being dirtied
    }

     

    1. 當(dāng)前測試方法后清理上下文。

如果在使用@ContextHierarchy將上下文配置為上下文層次結(jié)構(gòu)的一部分的測試中使用@DirtiesContext,則可以使用hierarchyMode標(biāo)志控制清除上下文緩存的方式。默認(rèn)情況下,使用窮舉算法清除上下文緩存,不僅包括當(dāng)前級別,還包括共享當(dāng)前測試共有的祖先上下文的所有其他上下文層次結(jié)構(gòu)。駐留在公共祖先上下文的子層次結(jié)構(gòu)中的所有ApplicationContext實(shí)例都將從上下文緩存中刪除并關(guān)閉。如果窮舉算法對于特定用例來說過于強(qiáng)大,那么你可以指定更簡單的當(dāng)前級別算法,如下面的示例所示。

@ContextHierarchy({
    @ContextConfiguration("/parent-config.xml"),
    @ContextConfiguration("/child-config.xml")
})
class BaseTests {
    // class body...
}

class ExtendedTests extends BaseTests {

    @Test
    @DirtiesContext(hierarchyMode = CURRENT_LEVEL) //1
    void test() {
        // some logic that results in the child context being dirtied
    }
}
  1. 使用當(dāng)前級別的算法。

有關(guān)EXHAUSTIVECURRENT_LEVEL算法的更多詳細(xì)信息,請參見DirtiesContext.HierarchyMode javadoc。

@TestExecutionListeners

@TestExecutionListeners定義了用于配置應(yīng)在TestContextManager中注冊的TestExecutionListener實(shí)現(xiàn)的類級元數(shù)據(jù)。通常,@TestExecutionListeners@ContextConfiguration結(jié)合使用。

下面的示例演示如何注冊兩個(gè)TestExecutionListener實(shí)現(xiàn):

@ContextConfiguration
@TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class}) //1
class CustomTestExecutionListenerTests {
    // class body...
}
  1. 注冊兩個(gè)TestExecutionListener實(shí)現(xiàn)。

默認(rèn)情況下,@TestExecutionListeners支持繼承的監(jiān)聽器。有關(guān)示例和更多詳細(xì)信息,請參見javadoc。

@Commit

@Commit表示應(yīng)在測試方法完成后提交用于事務(wù)性測試方法的事務(wù)。你可以將@Commit用作@Rollback(false)的直接替代品,以更明確地傳達(dá)代碼的意圖。與@Rollback類似,@ Commit也可以聲明為類級別或方法級別的注解。

以下示例顯示了如何使用@Commit注解:

@Commit //1
@Test
void testProcessWithoutRollback() {
    // ...
}
  1. 將測試結(jié)果提交到數(shù)據(jù)庫。

@Rollback

@Rollback表示在測試方法完成后是否應(yīng)回退用于事務(wù)性測試方法的事務(wù)。如果為true,則回滾該事務(wù)。否則,將提交事務(wù)(另請參見@Commit)。即使未明確聲明@Rollback,Spring TestContext框架中用于集成測試的回滾默認(rèn)為true。

當(dāng)聲明為類級注解時(shí),@Rollback定義測試類層次結(jié)構(gòu)中所有測試方法的默認(rèn)回滾語義。當(dāng)聲明為方法級別的注解時(shí),@Rollback定義特定測試方法的回滾語義,從而可能覆蓋類級別的@Rollback@Commit語義。

以下示例使測試方法的結(jié)果不回滾(即,結(jié)果已提交到數(shù)據(jù)庫):

@Rollback(false) //1
@Test
void testProcessWithoutRollback() {
    // ...
}
  1. 不要回滾結(jié)果。

@BeforeTransaction

@BeforeTransaction表示,對于已配置為使用Spring的@Transactional注解在事務(wù)內(nèi)運(yùn)行的測試方法,帶注解的void方法應(yīng)在事務(wù)開始之前運(yùn)行。@BeforeTransaction方法不需要public訪問限定,可以在基于Java 8的接口默認(rèn)方法。

以下示例顯示了如何使用@BeforeTransaction注解:

@BeforeTransaction //1
void beforeTransaction() {
    // logic to be executed before a transaction is started
}
  1. 在事務(wù)之前運(yùn)行此方法。

@AfterTransaction

@AfterTransaction表示,對于已配置為通過使用Spring的@Transactional注解在事務(wù)內(nèi)運(yùn)行的測試方法,帶注解的void方法應(yīng)在事務(wù)結(jié)束后運(yùn)行。@AfterTransaction方法不需要public訪問限定,可以在基于Java 8的接口默認(rèn)方法中聲明。

@AfterTransaction //1
void afterTransaction() {
    // logic to be executed after a transaction has ended
}
  1. 事務(wù)后運(yùn)行此方法。

@Sql

@Sql用于注解測試類或測試方法,以配置在集成測試期間針對給定數(shù)據(jù)庫運(yùn)行的SQL腳本。以下示例顯示了如何使用它:

@Test
@Sql({"/test-schema.sql", "/test-user-data.sql"})//1
void userTest() {
    // execute code that relies on the test schema and test data
}
  1. 運(yùn)行此測試的兩個(gè)腳本。

@SqlConfig

@SqlConfig定義元數(shù)據(jù),該元數(shù)據(jù)用于確定如何解析和運(yùn)行使用@Sql注解配置的SQL腳本。以下示例顯示了如何使用它:

@Test
@Sql(
    scripts = "/test-user-data.sql",
    config = @SqlConfig(commentPrefix = "`", separator = "@@") //
)
void userTest() {
    // execute code that relies on the test data
}
  1. 在SQL腳本中設(shè)置注釋前綴和分隔符。

@SqlMergeMode

@SqlMergeMode用于注釋測試類或測試方法,以配置是否將方法級@Sql聲明與類級@Sql聲明合并。如果未在測試類或測試方法上聲明@SqlMergeMode,則默認(rèn)情況下將使用OVERRIDE合并模式。在OVERRIDE模式下,方法級別的@Sql聲明將有效地覆蓋類級別的@Sql聲明。

請注意,方法級別的@SqlMergeMode聲明將覆蓋類級別的聲明。

下面的示例演示如何在類級別使用@SqlMergeMode

@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
@SqlMergeMode(MERGE) //1
class UserTests {

    @Test
    @Sql("/user-test-data-001.sql")
    void standardUserProfile() {
        // execute code that relies on test data set 001
    }
}
  1. 對于類中的所有測試方法,將@Sql合并模式設(shè)置為MERGE

下面的示例演示如何在方法級別使用@SqlMergeMode。

@SpringJUnitConfig(TestConfig.class)
@Sql("/test-schema.sql")
class UserTests {

    @Test
    @Sql("/user-test-data-001.sql")
    @SqlMergeMode(MERGE) //1
    void standardUserProfile() {
        // execute code that relies on test data set 001
    }
}

對于特定的測試方法,將@Sql合并模式設(shè)置為MERGE。

@SqlGroup

@SqlGroup是一個(gè)容器注解,它聚合了多個(gè)@Sql注解。你可以本地使用@SqlGroup聲明多個(gè)嵌套的@Sql注解,也可以將其與Java 8對可重復(fù)注解的支持結(jié)合使用,其中@Sql可以在同一類或方法上多次聲明,從而隱式生成此容器注解。下面的示例顯示如何聲明一個(gè)SQL組:

@Test
@SqlGroup({ //1
    @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")),
    @Sql("/test-user-data.sql")
)}
void userTest() {
    // execute code that uses the test schema and test data
}
  1. 聲明一組SQL腳本。

3.4.2 標(biāo)準(zhǔn)注解支持

Spring TestContext 框架的所有配置的標(biāo)準(zhǔn)語義都支持以下注解。請注意,這些注解并非特定于測試,可以在Spring 框架中的任何地方使用。

  • @Autowired

  • @Qualifier

  • @Value

  • @Resource (javax.annotation) 如果支持JSR-250

  • @ManagedBean (javax.annotation) 如果支持 JSR-250

  • @Inject (javax.inject) 如果支持 JSR-330

  • @Named (javax.inject) 如果支持 JSR-330

  • @PersistenceContext (javax.persistence) 如果支持JPA

  • @PersistenceUnit (javax.persistence) 如果支持JPA

  • @Required

  • @Transactional (org.springframework.transaction.annotation) with limited attribute support

JSR-250生命周期注解

在Spring TestContext 框架中,可以在ApplicationContext中配置的任何應(yīng)用程序組件上使用具有標(biāo)準(zhǔn)語義的@PostConstruct@PreDestroy。但是,這些生命周期注解在實(shí)際測試類中的使用受到限制。

如果測試類中的方法使用@PostConstruct進(jìn)行注解,則該方法將在基礎(chǔ)測試框架的before方法之前運(yùn)行(例如,使用JUnit Jupiter的@BeforeEach注解的方法),并且該方法適用于測試類中的每個(gè)測試方法。另一方面,如果測試類中的方法使用@PreDestroy注解,則該方法將永遠(yuǎn)不會(huì)運(yùn)行。因此,在測試類中,建議你使用來自基礎(chǔ)測試框架的測試生命周期回調(diào),而不是@PostConstruct@PreDestroy。

3.4.3 Spring JUnit4測試注解

以下注解僅在與SpringRunner、Spring的JUnit 4規(guī)則或Spring的JUnit 4支持類一起使用時(shí)才受支持:

  • @IfProfileValue

  • @ProfileValueSourceConfiguration

  • @Timed

  • @Repeat

@IfProfileValue

@IfProfileValue表示已為特定測試環(huán)境啟用帶注解的測試。如果配置的ProfileValueSource返回提供的名稱的匹配值,則使用測試。否則,測試將被禁用,并且實(shí)際上將被忽略。

你可以在類級別、方法級別或兩者上應(yīng)用@IfProfileValue。對于該類或其子類中的任何方法,@IfProfileValue的類級別用法優(yōu)先于方法級別用法。具體來說,如果在類級別和方法級別都啟用了測試,則啟用該測試。缺少@IfProfileValue意味著隱式啟用了測試。這類似于JUnit 4的@Ignore注解的語義,不同之處在于@Ignore的存在始終會(huì)禁用測試。

以下示例顯示了具有@IfProfileValue注解的測試:

@IfProfileValue(name="java.vendor", value="Oracle Corporation") //1
@Test
public void testProcessWhichRunsOnlyOnOracleJvm() {
    // some logic that should run only on Java VMs from Oracle Corporation
}
  1. 僅當(dāng)Java供應(yīng)商是“ Oracle Corporation”時(shí)才運(yùn)行此測試。

另外,你可以為@IfProfileValue配置值列表(具有OR語義)以在JUnit 4環(huán)境中實(shí)現(xiàn)類似于TestNG的測試組支持。考慮以下示例:

@IfProfileValue(name="test-groups", values={"unit-tests", "integration-tests"}) //1
@Test
public void testProcessWhichRunsForUnitOrIntegrationTestGroups() {
    // some logic that should run only for unit and integration test groups
}
  1. 對單元測試和集成測試運(yùn)行此測試。

@ProfileValueSourceConfiguration

@ProfileValueSourceConfiguration是一個(gè)類級別的注解,它指定檢索通過@IfProfileValue注解配置的配置文件值時(shí)要使用哪種ProfileValueSource類型。如果未為測試聲明@ProfileValueSourceConfiguration,則默認(rèn)使用SystemProfileValueSource。以下示例顯示了如何使用@ProfileValueSourceConfiguration

@ProfileValueSourceConfiguration(CustomProfileValueSource.class) //1
public class CustomProfileValueSourceTests {
    // class body...
}
  1. 使用自定義配置文件值源。

@Timed

@Timed表示帶注解的測試方法必須在指定的時(shí)間段(以毫秒為單位)內(nèi)完成執(zhí)行。如果單元測試片段執(zhí)行時(shí)間超過指定的時(shí)間段,則測試將失敗。

該時(shí)間段包括運(yùn)行測試方法本身,測試的任何重復(fù)(請參見@Repeat)以及測試套件的任何設(shè)置或拆除。以下示例顯示了如何使用它:

@Timed(millis = 1000)//1
public void testProcessWithOneSecondTimeout() {
    // some logic that should not take longer than 1 second to execute
}
  1. 將測試時(shí)間設(shè)置為一秒。

Spring的@Timed注解與JUnit 4的@Test(timeout = ...)支持具有不同的語義。具體來說,由于JUnit 4處理測試執(zhí)行超時(shí)的方式(即通過在單獨(dú)的線程中執(zhí)行測試方法),如果測試花費(fèi)的時(shí)間太長,@Test(timeout = ...)會(huì)搶先通過測試。另一方面,Spring的@Timed不會(huì)搶先通過測試,而是在失敗之前等待測試完成。

@Repeat

@Repeat表示必須重復(fù)運(yùn)行帶注解的測試方法。注解中指定了要執(zhí)行測試方法的次數(shù)。重復(fù)執(zhí)行的范圍包括測試方法本身的執(zhí)行以及測試套件中任何安裝或拆除。以下示例顯示了如何使用@Repeat注解:

@Repeat(10) //1
@Test
public void testProcessRepeatedly() {
    // ...
}
  1. 重復(fù)此測試十次。

3.4.4 Spring JUnit Jupiter測試注解

以下注解僅在與SpringExtensionJUnit Jupiter(即JUnit 5中的編程模型)結(jié)合使用時(shí)才受支持:

  • @SpringJUnitConfig

  • @SpringJUnitWebConfig

  • @TestConstructor

  • @EnabledIf

  • @DisabledIf

@SpringJUnitConfig

@SpringJUnitConfig是一個(gè)組合注解,它將JUnit Jupiter中的@ExtendWith(SpringExtension.class)與Spring TestContext 框架中的@ContextConfiguration組合在一起。它可以在類級別用作@ContextConfiguration的直接替代。關(guān)于配置選項(xiàng),@ContextConfiguration@SpringJUnitConfig之間的唯一區(qū)別是可以使用@SpringJUnitConfig中的value屬性聲明組件類。

以下示例顯示如何使用@SpringJUnitConfig注解指定配置類:

@SpringJUnitConfig(TestConfig.class) //1
class ConfigurationClassJUnitJupiterSpringTests {
    // class body...
}
  1. 指定配置類。

以下示例顯示如何使用@SpringJUnitConfig注解指定配置文件的位置:

@SpringJUnitConfig(locations = "/test-config.xml") //1
class XmlJUnitJupiterSpringTests {
    // class body...
}
  1. 指定配置文件的位置。

@SpringJUnitWebConfig

@SpringJUnitWebConfig是一個(gè)組合的注解,它將來自JUnit Jupiter@ExtendWith(SpringExtension.class)與來自Spring TestContext 框架的@ContextConfiguration@WebAppConfiguration組合在一起。你可以在類級別使用它作為@ContextConfiguration@WebAppConfiguration的直接替代。關(guān)于配置選項(xiàng),@ ContextConfiguration@SpringJUnitWebConfig之間的唯一區(qū)別是可以使用@SpringJUnitWebConfig中的value屬性來聲明組件類。另外,只能使用@SpringJUnitWebConfig中的resourcePath屬性來覆蓋@WebAppConfiguration中的value屬性。

以下示例顯示如何使用@SpringJUnitWebConfig注解指定配置類:

@SpringJUnitWebConfig(TestConfig.class) //1
class ConfigurationClassJUnitJupiterSpringWebTests {
    // class body...
}
  1. 指定配置類。

以下示例顯示如何使用@SpringJUnitWebConfig注解指定配置文件的位置:

@SpringJUnitWebConfig(locations = "/test-config.xml") //1
class XmlJUnitJupiterSpringWebTests {
    // class body...
}
  1. 指定配置文件的位置。

有關(guān)更多詳細(xì)信息,請參見上下文管理以及@SpringJUnitWebConfig,@ContextConfiguration和@WebAppConfiguration的javadoc。

@TestConstructor

@TestConstructor是類型級別的注解,用于配置如何從測試的ApplicationContext中的組件自動(dòng)連接測試類構(gòu)造函數(shù)的參數(shù)。

如果在測試類上不存在@TestConstructormeta-present,則將使用默認(rèn)的測試構(gòu)造函數(shù)自動(dòng)裝配模式。有關(guān)如何更改默認(rèn)模式的詳細(xì)信息,請參見下面的提示。但是請注意,構(gòu)造函數(shù)上的@Autowired本地聲明優(yōu)先于@TestConstructor和默認(rèn)模式。

更改默認(rèn)的測試構(gòu)造函數(shù)自動(dòng)裝配模式

可以通過將JVM系統(tǒng)屬性spring.test.constructor.autowire.mode設(shè)置為all來更改默認(rèn)的測試構(gòu)造函數(shù)自動(dòng)裝配模式。或者,可以通過SpringProperties機(jī)制更改默認(rèn)模式。

如果未設(shè)置spring.test.constructor.autowire.mode屬性,則不會(huì)自動(dòng)裝配測試類構(gòu)造函數(shù)。

從Spring框架5.2開始,僅將@TestConstructorSpringExtension結(jié)合使用以與JUnit Jupiter一起使用。請注意,SpringExtension通常會(huì)自動(dòng)為你注冊-例如,在使用@SpringJUnitConfig@SpringJUnitWebConfig之類的注解或Spring Boot Test中與測試相關(guān)的各種注解時(shí)。

@EnabledIf

@EnabledIf用于表示已注解的JUnit Jupiter測試類或測試方法啟用,如果提供的表達(dá)式的值為true,則應(yīng)運(yùn)行@EnabledIf。具體來說,如果表達(dá)式的計(jì)算結(jié)果為Boolean.TRUE或等于true的字符串(忽略大小寫),則啟用測試。在類級別應(yīng)用時(shí),默認(rèn)情況下也會(huì)自動(dòng)啟用該類中的所有測試方法。

表達(dá)式可以是以下任意一種:

  • Spring表達(dá)式語言。例如:@EnabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")

  • Spring Environment中可用屬性的占位符。例如:@EnabledIf("${smoke.tests.enabled}")

  • 文本文字。例如:@EnabledIf("true")

但是請注意,不是屬性占位符的動(dòng)態(tài)解析結(jié)果的文本文字的實(shí)際值為零,因?yàn)?code>@EnabledIf(“ false”)等效于@Disabled,而@EnabledIf(“ true”)在邏輯上是沒有意義的。

你可以使用@EnabledIf作為元注解來創(chuàng)建自定義的組合注釋。例如,你可以創(chuàng)建一個(gè)自定義@EnabledOnMac注解,如下所示:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@EnabledIf(
    expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
    reason = "Enabled on Mac OS"
)
public @interface EnabledOnMac {}

@DisabledIf

@DisabledIf用于表示已注解的JUnit Jupiter測試類或測試方法被禁用,并且如果提供的表達(dá)式的值為true,則不應(yīng)執(zhí)行該操作。具體來說,如果表達(dá)式的計(jì)算結(jié)果為Boolean.TRUE或等于true的字符串(忽略大小寫),則測試將被禁用。當(dāng)在類級別應(yīng)用時(shí),該類中的所有測試方法也會(huì)自動(dòng)禁止。

表達(dá)式可以是以下任意一種:

  • Spring表達(dá)式語言。例如:@DisabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")

  • Spring Environment中可用屬性的占位符。例如:@DisabledIf("${smoke.tests.disabled}")

  • 文本文字:例如:@DisabledIf("true")

但是請注意,不是屬性占位符的動(dòng)態(tài)解析結(jié)果的文本文字的實(shí)際值為零,因?yàn)?code>@DisabledIf(“ true”)等效于@Disabled,而@DisabledIf(“ false”)在邏輯上是沒有意義的。

你可以將@DisabledIf用作元注釋,以創(chuàng)建自定義的組合注解。例如,你可以創(chuàng)建一個(gè)自定義@DisabledOnMac注解,如下所示:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@DisabledIf(
    expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}",
    reason = "Disabled on Mac OS"
)
public @interface DisabledOnMac {}

3.4.5 測試的元注解支持

你可以將大多數(shù)與測試相關(guān)的注解用作元注解,以創(chuàng)建自定義的組合注解,并減少整個(gè)測試套件中的重復(fù)配置。

你可以將以下各項(xiàng)用作與TestContext框架結(jié)合使用的元注解。

  • @BootstrapWith

  • @ContextConfiguration

  • @ContextHierarchy

  • @ActiveProfiles

  • @TestPropertySource

  • @DirtiesContext

  • @WebAppConfiguration

  • @TestExecutionListeners

  • @Transactional

  • @BeforeTransaction

  • @AfterTransaction

  • @Commit

  • @Rollback

  • @Sql

  • @SqlConfig

  • @SqlMergeMode

  • @SqlGroup

  • @Repeat (僅支持 JUnit 4)

  • @Timed (僅支持 JUnit 4)

  • @IfProfileValue (僅支持 JUnit 4)

  • @ProfileValueSourceConfiguration (僅支持 JUnit 4)

  • @SpringJUnitConfig (僅支持 JUnit Jupiter)

  • @SpringJUnitWebConfig (僅支持JUnit Jupiter)

  • @TestConstructor (僅支持 JUnit Jupiter)

  • @EnabledIf (僅支持 JUnit Jupiter)

  • @DisabledIf (僅支持 JUnit Jupiter)

考慮以下示例:

@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class OrderRepositoryTests { }

@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class UserRepositoryTests { }

如果發(fā)現(xiàn)我們要在基于JUnit 4的測試套件中重復(fù)上述配置,則可以通過引入一個(gè)自定義的組合注解來減少重復(fù),該注解集中了Spring的通用測試配置,如下所示:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }

然后,我們可以使用我們的自定義@TransactionalDevTestConfig的注解來簡化單個(gè)基于JUnit 4的測試類的配置,如下所示:

@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class OrderRepositoryTests { }

@RunWith(SpringRunner.class)
@TransactionalDevTestConfig
public class UserRepositoryTests { }

如果我們編寫使用JUnit Jupiter的測試,則可以進(jìn)一步減少代碼重復(fù),因?yàn)镴Unit 5中的注解也可以用作元注解。考慮以下示例:

@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
class OrderRepositoryTests { }

@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
class UserRepositoryTests { }

如果發(fā)現(xiàn)我們在基于JUnit Jupiter的測試套件中重復(fù)了前面的配置,則可以通過引入一個(gè)自定義組合注解來減少重復(fù),該注解集中了Spring和JUnit Jupiter的通用測試配置,如下所示:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTestConfig { }

然后,我們可以使用我們的自定義@TransactionalDevTestConfig的注解來簡化基于單個(gè)JUnit Jupiter的測試類的配置,如下所示:

@TransactionalDevTestConfig
class OrderRepositoryTests { }

@TransactionalDevTestConfig
class UserRepositoryTests { }

由于JUnit Jupiter支持使用@Test、@RepeatedTest、ParameterizedTest和其他作為元注解,因此你也可以在測試方法級別創(chuàng)建自定義的組合注解。例如,如果我們希望創(chuàng)建一個(gè)組合的注解,將JUnit Jupiter的@Test@Tag注解與Spring的@Transactional注解相結(jié)合,則可以創(chuàng)建一個(gè)@TransactionalIntegrationTest注解,如下所示:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Transactional
@Tag("integration-test") // org.junit.jupiter.api.Tag
@Test // org.junit.jupiter.api.Test
public @interface TransactionalIntegrationTest { }

然后,我們可以使用自定義的@TransactionalIntegrationTest注解來簡化基于單個(gè)JUnit Jupiter的測試方法的配置,如下所示:

@TransactionalIntegrationTest
void saveOrder() { }

@TransactionalIntegrationTest
void deleteOrder() { }

到此,相信大家對“Spring集成測試方法是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI