3.5.5 上下文管理
每個
TestContext
為其負責的測試執行個體提供上下文管理和緩存支援。測試執行個體不會自動接收對配置的 ApplicationContext
的通路。但是,如果測試類實作 ApplicationContextAware
接口,則将對 ApplicationContext
的引用提供給測試執行個體。請注意, AbstractJUnit4SpringContextTests
和 AbstractTestNGSpringContextTests
實作了 ApplicationContextAware
,是以可以自動提供對 ApplicationContext
的通路。
@Autowired
作為實作
ApplicationContext
接口的替代方法,你可以通過字段或
ApplicationContextAware
方法上的
setter
注解為測試類注入應用程式上下文,如以下示例所示:
@Autowired
@SpringJUnitConfig class MyTest { @Autowired //1 ApplicationContext applicationContext; // class body... }
同樣,如果将測試配置為加載
- 注入
。
ApplicationContext
,則可以将Web應用程式上下文注入到測試中,如下所示:
WebApplicationContext
@SpringJUnitWebConfig //1 class MyWebAppTest { @Autowired //2 WebApplicationContext wac; // class body... }
使用
- 配置
WebApplicationContext
WebApplicationContext
的依賴關系注入是
@Autowired
提供的,它是預設配置的( 參見測試裝置的依賴注入 )。
DependencyInjectionTestExecutionListener
TestContext
架構的測試類不需要擴充任何特定的類或實作特定的接口來配置其應用程式上下文。而是通過在類級别聲明
@ContextConfiguration
注解來實作配置。如果你的測試類未明确聲明應用程式上下文資源位置或元件類,則配置的
ContextLoader
将确定如何從預設位置或預設配置類加載上下文。除了上下文資源位置群組件類之外,還可以通過應用程式上下文初始化程式配置應用程式上下文。
以下各節說明如何使用Spring的
@ContextConfiguration
注解通過XML配置檔案、
Groovy
腳本、元件類(通常為
@Configuration
類)或上下文初始化器來配置測試
ApplicationContext
。另外,你可以為進階用例實作和配置自己的自定義
SmartContextLoader
- 通過XML資源配置上下文
- 通過Groovy腳本配置上下文
- 通過元件類配置上下文
- XML、Groovy腳本、元件類混合
- 通過上下文初始化器配置上下文
- 上下文配置繼承
- 通過環境配置配置上下文
- 通過測試屬性源配置上下文
- 通過動态屬性源配置上下文
- 加載
WebApplicationContext
- 上下文緩存
- 上下文層級
若要使用XML配置檔案為測試加載
ApplicationContext
,請使用
@ContextConfiguration
注解測試類,并使用包含XML配置中繼資料的資源位置的數組配置
locations
屬性。簡單路徑或相對路徑(例如
context.xml
)被視為相對于定義測試類的程式包的類路徑資源。以斜杠開頭的路徑被視為絕對類路徑位置(例如:
/org/example/config.xml
)。照原樣使用表示資源URL的路徑(即以
classpath:
、
file:
http:
等開頭的路徑)。
@ExtendWith(SpringExtension.class)
// ApplicationContext從根路徑加載"/app-config.xml" 和
// "/test-config.xml"
@ContextConfiguration(locations={"/app-config.xml", "/test-config.xml"}) //1
class MyTest {
// class body...
}
- 将
屬性設定為XML檔案清單。locations
@ContextConfiguration
通過标準Java值屬性為
locations
屬性支援别名。是以,如果不需要在
@ContextConfiguration
中聲明其他屬性,你可以使用以下示例中示範的格式,省略
locations
屬性名稱的聲明并聲明資源位置。
@ExtendWith(SpringExtension.class)
@ContextConfiguration({"/app-config.xml", "/test-config.xml"}) //1
class MyTest {
// class body...
}
- 不使用
屬性指定XML檔案。location
如果你從
@ContextConfiguration
注解中省略了位置和值屬性,則
TestContext
架構将嘗試檢測預設的XML資源位置。具體而言,
GenericXmlContextLoader
GenericXmlWebContextLoader
根據測試類的名稱檢測預設位置。如果你的類名為
com.example.MyTest
則
GenericXmlContextLoader
classpath:com/example/MyTest-context.xml
加載應用程式上下文。以下示例顯示了如何執行此操作:
@ExtendWith(SpringExtension.class)
// ApplicationContext will be loaded from
// "classpath:com/example/MyTest-context.xml"
@ContextConfiguration //1
class MyTest {
// class body...
}
- 從預設位置加載配置。
要通過使用
Groovy Bean定義DSL的Groovy腳本為測試加載
ApplicationContext
,可以使用
@ContextConfiguration
注解測試類,并使用包含Groovy腳本資源位置的數組配置
location
或
value
屬性。Groovy腳本的資源查找語義與針對
XML配置檔案描述的語義相同。
激活Groovy腳本支援
如果類路徑中有Groovy,那麼就會自動啟用使用Groovy腳本在Spring
架構中加載
TestContext
的支援。
ApplicationContext
下面的示例顯示如何指定Groovy配置檔案:
@ExtendWith(SpringExtension.class)
// ApplicationContext will be loaded from "/AppConfig.groovy" and
// "/TestConfig.groovy" in the root of the classpath
@ContextConfiguration({"/AppConfig.groovy", "/TestConfig.Groovy"})
class MyTest {
// class body...
}
@ContextConfiguration
注解中省略了
location
value
屬性,則
TestContext
架構将嘗試檢測預設的Groovy腳本。具體來說,
GenericGroovyXmlContextLoader
GenericGroovyXmlWebContextLoader
com.example.MyTest
則Groovy上下文加載器将從
classpath:com/example/MyTestContext.groovy
加載應用程式上下文。下面的示例示範如何使用預設值:
@ExtendWith(SpringExtension.class)
// ApplicationContext will be loaded from
// "classpath:com/example/MyTestContext.groovy"
@ContextConfiguration //1
class MyTest {
// class body...
}
同時聲明XML配置和Groovy腳本
你可以使用
的
@ContextConfiguration
location
屬性同時聲明XML配置檔案和Groovy腳本。如果到配置的資源位置的路徑以
value
結尾,則使用
.xml
加載該路徑。否則,将使用
XmlBeanDefinitionReader
GroovyBeanDefinitionReader
加載它。
以下清單顯示了如何在內建測試中将兩者結合起來:
@ExtendWith(SpringExtension.class) // ApplicationContext将從 // "/app-config.xml" 和 "/TestConfig.groovy"加載上下文 @ContextConfiguration({ "/app-config.xml", "/TestConfig.groovy" }) class MyTest { // class body... }
要使用元件類(請參見
基于Java的容器配置)為測試加載
ApplicationContext
@ContextConfiguration
注解測試類,并使用包含對元件類的引用的數組來配置
classes
屬性。以下示例顯示了如何執行此操作:
@ExtendWith(SpringExtension.class)
// ApplicationContext将從AppConfig和TestConfig加載上下文
@ContextConfiguration(classes = {AppConfig.class, TestConfig.class}) //1
class MyTest {
// class body...
}
- 指定元件類。
元件類
術語
可以指以下任何一種:
元件類
有關元件類的配置和語義的更多資訊,請參見 @Configuration @Bean 的javadoc,尤其要注意
- 用
注解的類。
@Configuration
- 元件(即,用
@Component
@Service
或其他構造型注解注釋的類)。
@Repository
- 與JSR-330相容的類,該類使用
注解進行了注釋。
javax.inject
- 包含
方法的任何類。
@Bean
- 打算注冊為Spring元件的任何其他類(即
中的Spring bean),可能利用單個自動構造函數的自動裝配而無需使用Spring注解。
ApplicationContext
Lite模式的讨論。
@Bean
@ContextConfiguration
classes
TestContext
架構将嘗試檢測預設配置類的存在。具體來說,
AnnotationConfigContextLoader
AnnotationConfigWebContextLoader
檢測到滿足配置類實作要求的測試類的所有靜态嵌套類,如
javadoc中所指定。請注意,配置類的名稱是任意的。另外,如果需要,一個測試類可以包含多個靜态嵌套配制類。在以下示例中,
OrderServiceTest
類聲明一個名為
Config
的靜态嵌套配置類,該配置類将自動用于為測試類加載
ApplicationContext
:
@SpringJUnitConfig //1
// ApplicationContext将從内部潛逃靜态累加載
class OrderServiceTest {
@Configuration
static class Config {
// this bean will be injected into the OrderServiceTest class
@Bean
OrderService orderService() {
OrderService orderService = new OrderServiceImpl();
// set properties, etc.
return orderService;
}
}
@Autowired
OrderService orderService;
@Test
void testOrderService() {
// test the orderService
}
}
- 從嵌套的Config類加載配置資訊。
有時可能需要混合使用XML配置檔案、Groovy腳本群組件類(通常為
@Configuration
類)來為測試配置
ApplicationContext
。如果在生産中使用XML配置,則可以決定要使用
@Configuration
類為測試配置特定的Spring托管元件,反之亦然。
此外,某些第三方架構(例如Spring Boot)提供了一流的支援,可以同時從不同類型的資源(例如XML配置檔案、Groovy腳本和
@Configuration
類)中加載
ApplicationContext
。過去,Spring架構不支援此标準部署。是以,Spring架構在
spring-test
子產品中提供的大多數
SmartContextLoader
實作對于每個測試上下文僅支援一種資源類型。但是,這并不意味着你不能同時使用兩者。通用規則的一個例外是
GenericGroovyXmlContextLoader
GenericGroovyXmlWebContextLoader
同時支援XML配置檔案和Groovy腳本。此外,第三方架構可以選擇通過
@ContextConfiguration
支援位置和類的聲明,并且,借助
TestContext
架構中的标準測試支援,你可以選擇以下選項。
如果要使用資源位置(例如XML或Groovy)和
@Configuration
類的配置測試,則必須選擇一個作為入口點,并且其中一個必須包含或導入另一個。例如,在XML或Groovy腳本中,可以通過使用元件掃描或将它們定義為普通的Spring bean來包括
@Configuration
類,而在
@Configuration
類中,可以使用
@ImportResource
導入XML配置檔案或Groovy腳本。請注意,此行為在語義上等同于你在生産環境中配置應用程式的方式:在生産配置中,你定義了一組XML或Groovy資源位置或一組
@Configuration
類,從中加載了生産
ApplicationContext
,但是你仍然包含或導入其他類型的配置的自由。
若要使用上下文初始化程式為你的測試配置
ApplicationContext
@ContextConfiguration
注解測試類,并使用包含對實作
ApplicationContextInitializer
的類的引用的數組配置初始化程式屬性。然後,使用聲明的上下文初始值設定項來初始化為測試加載的
ConfigurableApplicationContext
。請注意,每個聲明的初始化程式支援的具體
ConfigurableApplicationContext
類型必須與使用中的
SmartContextLoader
建立的
ApplicationContext
類型(通常是
GenericApplicationContext
)相容。此外,初始化程式的調用順序取決于它們是實作Spring的
Ordered
接口還是以Spring的
@Order
注解或标準的
@Priority
注解進行注釋。下面的示例示範如何使用初始化程式:
@ExtendWith(SpringExtension.class)
// ApplicationContext将從TestConfig
// 和 通過TestAppCtxInitializer初始化
@ContextConfiguration(
classes = TestConfig.class,
initializers = TestAppCtxInitializer.class) //1
class MyTest {
// class body...
}
- 使用配置類和初始化程式指定配置。
你還可以完全省略
@ContextConfiguration
中的XML配置檔案、Groovy腳本或元件類的聲明,而僅聲明
ApplicationContextInitializer
類,然後這些類負責在上下文中注冊Bean(例如,通過程式設計方式從XML檔案加載Bean定義)或配置類。以下示例顯示了如何執行此操作:
@ExtendWith(SpringExtension.class)
// ApplicationContext will be initialized by EntireAppInitializer
// which presumably registers beans in the context
@ContextConfiguration(initializers = EntireAppInitializer.class) //1
class MyTest {
// class body...
}
- 僅使用初始化程式來指定配置。
參考代碼: org.liyong.test.annotation.test.spring.ContextInitializerTests
@ContextConfiguration
支援
boolean
inheritLocations
inheritinitialalizer
屬性,它們表示是否應該繼承由超類聲明的資源位置或元件類和上下文初始化器。這兩個标志的預設值為
true
。這意味着測試類将繼承資源位置或元件類以及任何超類申明的上下文初始化器。具體來說,将測試類的資源位置或元件類附加到由超類申明的資源位置或帶注解的類的清單中。同樣,将給定測試類的初始化程式添加到由測試超類定義的初始化程式集。是以,子類可以選擇擴充資源位置、元件類或上下文初始化程式。
如果
@ContextConfiguration
中的
inheritLocations
inheritInitializers
屬性被設定為
false
,則測試類的資源位置或元件類和上下文初始化器将分别有效地替代超類定義的配置。
在下一個使用XML資源位置的示例中,從
Base-config.xml
Extended-config.xml依
次加載
ExtendedContext
ApplicationContext
。是以,
extended-config.xml
中定義的Bean可以覆寫(即替換)
base-config.xml
中定義的那些。以下示例顯示了一個類如何擴充另一個類并使用其自己的配置檔案和超類的配置檔案:
@ExtendWith(SpringExtension.class)
// ApplicationContext将從類路徑根目錄加載"/base-config.xml"
@ContextConfiguration("/base-config.xml") //1
class BaseTest {
// class body...
}
// ApplicationContext将從類路徑根目錄加載"/base-config.xml" 和
// "/extended-config.xml"
@ContextConfiguration("/extended-config.xml") //2
class ExtendedTest extends BaseTest {
// class body...
}
- 在超類中定義的配置檔案
- 子類中定義的配置檔案。
同樣,在下一個使用元件類的示例中,從
BaseConfig
ExtendedConfig
類按該順序加載
ExtendedTest
ApplicationContext
。是以,在
ExtendedConfig
中定義的Bean可以覆寫(即替換)在
BaseConfig
中定義的Bean。下面的示例顯示一個類如何擴充另一個類,并同時使用自己的配置類和超類的配置類:
// ApplicationContext從BaseConfig加載
@SpringJUnitConfig(BaseConfig.class) //1
class BaseTest {
// class body...
}
// ApplicationContext将從BaseConfig和ExtendedConfig加載
@SpringJUnitConfig(ExtendedConfig.class) //2
class ExtendedTest extends BaseTest {
// class body...
}
- 在超類中定義的配置類
- 在子類中定義的配置類。
在使用上下文初始化程式的下一個示例中,通過使用
BaseInitializer
ExtendedInitializer
初始化
ExtendedTest
ApplicationContext
。但是請注意,初始化程式的調用順序取決于它們是實作Spring的
Ordered
@Order
@Priority
注解進行注釋。以下示例顯示了一個類如何擴充另一個類并使用其自己的初始化程式和超類的初始化程式:
// ApplicationContext将通過BaseInitializer初始化
@SpringJUnitConfig(initializers = BaseInitializer.class) //1
class BaseTest {
// class body...
}
// ApplicationContext将通過BaseInitializer
// 和 ExtendedInitializer初始化
@SpringJUnitConfig(initializers = ExtendedInitializer.class) //2
class ExtendedTest extends BaseTest {
// class body...
}
- 超類中定義的初始化器。
- 子類中定義的初始化程式。
使用環境配置檔案進行上下文配置
Spring架構對環境和配置檔案(又名“bean定義配置檔案”)的概念提供了一流的支援,可以配置內建測試來激活針對各種測試場景的特定bean定義配置檔案。這可以通過使用
@ActiveProfiles
注解測試類并提供在加載測試的
ApplicationContext
時應激活的配置檔案清單來實作。
你可以将與
@ActiveProfiles
SPI的任何實作一起使用,但較早的
SmartContextLoader
SPI的實作不支援
ContextLoader
@ActiveProfiles
考慮兩個帶有XML配置和
@Configuration
類的示例:
<!-- app-config.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="...">
<bean id="transferService"
class="com.bank.service.internal.DefaultTransferService">
<constructor-arg ref="accountRepository"/>
<constructor-arg ref="feePolicy"/>
</bean>
<bean id="accountRepository"
class="com.bank.repository.internal.JdbcAccountRepository">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="feePolicy"
class="com.bank.service.internal.ZeroFeePolicy"/>
<beans profile="dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script
location="classpath:com/bank/config/sql/schema.sql"/>
<jdbc:script
location="classpath:com/bank/config/sql/test-data.sql"/>
</jdbc:embedded-database>
</beans>
<beans profile="production">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
</beans>
<beans profile="default">
<jdbc:embedded-database id="dataSource">
<jdbc:script
location="classpath:com/bank/config/sql/schema.sql"/>
</jdbc:embedded-database>
</beans>
</beans>
@ExtendWith(SpringExtension.class)
// ApplicationContext will be loaded from "classpath:/app-config.xml"
@ContextConfiguration("/app-config.xml")
@ActiveProfiles("dev")
class TransferServiceTest {
@Autowired
TransferService transferService;
@Test
void testTransferService() {
// test the transferService
}
}
運作
TransferServiceTest
時,會從類路徑根目錄中的
app-config.xml
配置檔案中加載其
ApplicationContext
。如果檢查
app-config.xml
,可以看到accountRepository bean對
dataSource
bean有依賴性。但是,
dataSource
未被定義為頂級bean。相反,
dataSource
定義了三次:在生産配置檔案中、在開發配置檔案中以及在預設配置檔案中。
通過使用
@ActiveProfiles(“dev”)
注解
TransferServiceTest
,我們訓示Spring
TestContext
架構加載具有設定為
{“dev”}
的激活配置檔案的
ApplicationContext
。結果,建立了一個嵌入式資料庫,并用測試資料填充了資料庫,并用對開發
DataSource
的引用來連接配接
accountRepository
bean。這可能是我們在內建測試中想要的。
有時将bean配置設定給預設配置檔案很有用。隻有在沒有特别激活其他配置檔案時,才會包含預設配置檔案中的bean。你可以使用它來定義在應用程式的預設狀态中使用的後備bean。例如,你可以顯式提供
dev
production
的資料源,但是當兩者都不處于活動狀态時,将記憶體中資料源定義為預設值。
以下代碼清單示範了如何使用
@Configuration
類而不是XML實作相同的配置和內建測試:
@Configuration
@Profile("dev")
public class StandaloneDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
@Configuration
@Profile("production")
public class JndiDataConfig {
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
@Configuration
@Profile("default")
public class DefaultDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.build();
}
}
@Configuration
public class TransferServiceConfig {
@Autowired DataSource dataSource;
@Bean
public TransferService transferService() {
return new DefaultTransferService(accountRepository(), feePolicy());
}
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
@Bean
public FeePolicy feePolicy() {
return new ZeroFeePolicy();
}
}
@SpringJUnitConfig({
TransferServiceConfig.class,
StandaloneDataConfig.class,
JndiDataConfig.class,
DefaultDataConfig.class})
@ActiveProfiles("dev")
class TransferServiceTest {
@Autowired
TransferService transferService;
@Test
void testTransferService() {
// test the transferService
}
}
在此變體中,我們将XML配置分為四個獨立的
@Configuration
類:
-
: 通過使用ransferServiceConfig
進行依賴項注入來擷取資料源。@Autowired
-
: 為适合開發人員測試的嵌入式資料庫定義資料源。StandaloneDataConfig
-
: 定義在生産環境中從JNDI檢索的資料源。JndiDataConfig
-
: 如果沒有配置檔案處于激活狀态,則為預設的嵌入式資料庫定義一個資料源。DefaultDataConfig
與基于XML的配置示例一樣,我們仍然使用
@ActiveProfiles("dev")
TransferServiceTest
,但是這次我們使用
@ContextConfiguration
注解指定所有四個配置類。測試類的主體本身保持完全不變。
在一個給定項目中,跨多個測試類使用一組配置檔案是很常見的。是以,為避免
@ActiveProfiles
注解的重複聲明,可以在基類中聲明一次
@ActiveProfiles
,子類會自動從基類繼承
@ActiveProfiles
配置。在以下示例中,
@ActiveProfiles
的聲明(以及其他注解)已移至抽象超類
AbstractIntegrationTest
@SpringJUnitConfig({
TransferServiceConfig.class,
StandaloneDataConfig.class,
JndiDataConfig.class,
DefaultDataConfig.class})
@ActiveProfiles("dev")
abstract class AbstractIntegrationTest {
}
// "dev"配置內建父類
class TransferServiceTest extends AbstractIntegrationTest {
@Autowired
TransferService transferService;
@Test
void testTransferService() {
// test the transferService
}
}
@ActiveProfiles
還支援可用于禁用激活配置檔案的繼承的
InheritedProfiles
屬性,如以下示例所示:
// "dev"配置被"production"覆寫
@ActiveProfiles(profiles = "production", inheritProfiles = false)
class ProductionTransferServiceTest extends AbstractIntegrationTest {
// test body
}
此外,有時有必要以程式設計方式而不是聲明方式來解析測試的激活配置檔案,例如,基于:
- 目前的作業系統。
- 是否在持續內建建構伺服器上執行測試。
- 存在某些環境變量。
- 自定義類級别注釋的存在。
- 其他問題。
要以程式設計方式解析活動bean定義配置檔案,可以實作自定義
ActiveProfilesResolver
并使用
@ActiveProfiles
resolver
屬性對其進行注冊。有關更多資訊,請參見相應的
javadoc。下面的示例示範如何實作和注冊自定義的
OperatingSystemActiveProfilesResolver
// "dev"配置通過自定義解析器程式設計式地覆寫
@ActiveProfiles(
resolver = OperatingSystemActiveProfilesResolver.class,
inheritProfiles = false)
class TransferServiceTest extends AbstractIntegrationTest {
// test body
}
public class OperatingSystemActiveProfilesResolver implements ActiveProfilesResolver {
@Override
public String[] resolve(Class<?> testClass) {
String profile = ...;
// determine the value of profile based on the operating system
return new String[] {profile};
}
}
Spring架構對具有屬性源層次結構的環境概念提供了一流的支援,你可以使用特定于測試的屬性源配置內建測試。與
@Configuration
類上使用的
@PropertySource
注解相反,可以在測試類上聲明
@TestPropertySource
注解,以聲明測試屬性檔案或内聯屬性的資源位置。這些測試屬性源被添加到環境中為帶注解的內建測試加載的
ApplicationContext
PropertySources
集合中。
@TestPropertySource
SPI的任何實作一起使用,但是較早的
SmartContextLoader
ContextLoader
@TestPropertySource
的實作可通過
SmartContextLoader
MergedContextConfiguration
getPropertySourceLocations()
方法通路合并的測試屬性源值。
getPropertySourceProperties()
聲明測試屬性源
@TestPropertySource的location
value
屬性來配置測試屬性檔案。
支援傳統屬性檔案格式和基于XML的屬性檔案格式,例如:
classpath:/com/example/test.properties
file:///path/to/file.xml
每個路徑都被解析為Spring資源。普通路徑(例如
test.properties
)被視為相對于定義測試類的程式包的類路徑資源。以斜杠開頭的路徑被視為絕對類路徑資源(例如:
/org/example/test.xml
)。通過使用指定的資源協定加載引用URL的路徑(例如,以
classpath:
file:
http:
為字首的路徑)。不允許使用資源位置通配符(例如
* /.properties
)每個位置都必須精确評估為一個
.properties
.xml
資源。
以下示例使用測試屬性檔案:
@ContextConfiguration
@TestPropertySource("/test.properties") //1
class MyIntegrationTests {
// class body...
}
- 指定具有絕對路徑的屬性檔案。
@TestPropertySource
properties
屬性,以鍵/值對的形式配置内聯屬性,如下例所示。所有鍵值對都作為優先級最高的單個測試
PropertySource
添加到封閉環境中。
鍵值對支援的文法與為Java屬性檔案中的條目定義的文法相同:
-
key=value
-
key:value
-
key value
下面的示例設定兩個内聯屬性:
@ContextConfiguration
@TestPropertySource(properties = {"timezone = GMT", "port: 4242"}) //1
class MyIntegrationTests {
// class body...
}
- 通過使用鍵值文法的兩種變體來設定兩個屬性。
從Spring架構5.2開始,可以用作可重複注解。這意味着你可以在單個測試類上具有
@TestPropertySource
的多個聲明,其後的
@TestPropertySource
注解中的
@TestPropertySource
locations
将覆寫先前的
properties
@TestPropertySource
locations
此外,你可以在一個測試類上聲明多個組合注解,每個注解都用
properties
進行元注解,所有這些
@TestPropertySource
聲明都将貢獻給你的測試屬性源。直接呈現的
@TestPropertySource
總是優先于元呈現的
@TestPropertySource注解
注解。換句話說,直接存在的
@TestPropertySource
@TestPropertySource
locations
将覆寫
properties
注解中用作元注解的
@TestPropertySource
locations
properties
預設屬性檔案檢測
@TestPropertySource
被聲明為空注解(即,沒有
locations
properties
的顯式值),則嘗試檢測相對于聲明該注解的類的預設屬性檔案。例如,如果帶注解的測試類是
com.example.MyTest
,則相應的對應屬性檔案是
classpath:com/example/MyTest.properties
。如果無法檢測到預設值,則抛出
IllegalStateException
優先順序
測試屬性的優先級高于在作業系統環境、Java系統屬性或應用程式通過使用
@PropertySource
聲明性地或以程式設計方式添加的屬性源中定義的屬性。是以,測試屬性可用于有選擇地覆寫從系統和應用程式屬性源加載的屬性。此外,内聯屬性優先于從資源位置加載的屬性。但是請注意,通過
@DynamicPropertySource
注冊的屬性比通過
@TestPropertySource
加載的屬性具有更高的優先級。
在下一個示例中,
timezone
port
屬性以及在
/test.properties
中定義的任何屬性都将覆寫在系統和應用程式屬性源中定義的同名屬性。此外,如果
/test.properties
檔案定義了
timezone
port
屬性的條目,則這些條目将被使用
properties
屬性聲明的内聯屬性所覆寫。
@ContextConfiguration
@TestPropertySource(
locations = "/test.properties",
properties = {"timezone = GMT", "port: 4242"}
)
class MyIntegrationTests {
// class body...
}
繼承和覆寫測試屬性源
@TestPropertySource
支援布爾型的
inheritLocations
inheritProperties
屬性,它們表示屬性檔案的資源位置和超類聲明的内聯屬性是否應該被繼承。這兩個标志的預設值為
true
。這意味着測試類将繼承任何超類聲明的位置和内聯屬性。具體來說,測試類的位置和内聯屬性附加到父類聲明的位置和内聯屬性。是以,子類可以選擇擴充位置和内聯屬性。注意,後面出現的屬性會隐藏(即覆寫)前面出現的同名屬性。此外,前面提到的優先規則也适用于繼承的測試屬性源。
@TestPropertySource
InheritLocations
InheritProperties
屬性設定為
false
,則分别為測試類設定位置或内聯屬性,并有效替換超類定義的配置。
BaseTest
ApplicationContext
是通過隻使用
base
加載的。屬性檔案作為測試屬性源。相反,
ExtendedTest
ApplicationContext
是通過使用
base
加載的屬性和擴充。屬性檔案作為測試屬性源位置。下面的示例示範如何使用屬性檔案在子類及其超類中定義屬性:
@TestPropertySource("base.properties")
@ContextConfiguration
class BaseTest {
// ...
}
@TestPropertySource("extended.properties")
@ContextConfiguration
class ExtendedTest extends BaseTest {
// ...
}
在下一個示例中,僅使用内聯的
key1
屬性來加載
BaseTest
ApplicationContext
。相反,使用内聯的
key1
key2
ExtendedTest
ApplicationContext
。下面的示例示範如何通過使用内聯屬性在子類及其父類中定義屬性:
@TestPropertySource(properties = "key1 = value1")
@ContextConfiguration
class BaseTest {
// ...
}
@TestPropertySource(properties = "key2 = value2")
@ContextConfiguration
class ExtendedTest extends BaseTest {
// ...
}
從Spring架構5.2.5開始,
TestContext
架構通過
@DynamicPropertySource
注解提供對動态屬性的支援。此注解可用于需要向為內建測試加載的
ApplicationContext
的環境中的
PropertySources
集添加帶有動态值的屬性的內建測試。
注解及其支援的基礎結構最初旨在使基于
@DynamicPropertySource
的測試中的屬性易于暴露于Spring內建測試。但是,此功能還可以用于其生命周期在測試的
Testcontainers
之外維護的任何形式的外部資源。
ApplicationContext
與在類級别應用
@TestPropertySource
注解相反,
@DynamicPropertySource
必須應用于接受單個
DynamicPropertyRegistry
參數的靜态方法,該參數用于向環境添加
名稱/值
對。值是動态的,并通過
Supplier
提供,隻有在解析屬性時才調用
Supplier
。通常,方法引用被用來提供值,如下面的例子所示,它使用
Testcontainers
項目在Spring
ApplicationContext
之外管理一個Redis容器。通過
redis.host
redis.port
屬性,測試的
ApplicationContext
中的元件可以使用托管Redis容器的IP位址和端口。這些屬性可以通過Spring的環境抽象通路,或者直接注入到Spring管理的元件中,例如分别通過
@Value("${redis.host}")
@Value("${redis.port}")
@SpringJUnitConfig(/* ... */)
@Testcontainers
class ExampleIntegrationTests {
@Container
static RedisContainer redis = new RedisContainer();
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
registry.add("redis.host", redis::getContainerIpAddress);
registry.add("redis.port", redis::getMappedPort);
}
// tests ...
}
動态屬性的優先級高于
@TestPropertySource
、作業系統的環境、Java系統屬性或應用程式通過
@PropertySource
聲明性地或以程式設計方式添加的屬性源中加載的屬性。是以,動态屬性可用于有選擇地覆寫通過
@TestPropertySource
、系統屬性源和應用程式屬性源加載的屬性。
WebApplicationContext
若要訓示
TestContext
架構加載
WebApplicationContext
而不是标準
ApplicationContext
@WebAppConfiguration
注解各自的測試類。
測試類上
@WebAppConfiguration
的存在訓示
TestContext
架構(TCF)應該為內建測試加載
WebApplicationContext
(WAC)。TCF在背景確定建立了
MockServletContext
并将其提供給測試的WAC。預設情況下,你的
MockServletContext
的基本資源路徑設定為
src/main/webapp
。這被解釋為相對于JVM根目錄的路徑(通常是項目的路徑)。如果你熟悉Maven項目中Web應用程式的目錄結構,則知道
src/main/webapp
是WAR根目錄的預設位置。如果需要覆寫此預設值,則可以提供
@WebAppConfiguration
注解的替換路徑(例如,
@WebAppConfiguration(“src/test/webapp”))
。如果你希望從類路徑而不是檔案系統中引用基本資源路徑,則可以使用Spring的
classpath:
字首。
請注意,Spring對
WebApplicationContext
實作的測試支援與其對标準
ApplicationContext
實作的支援相當。使用
WebApplicationContext
進行測試時,可以使用
@ContextConfiguration
聲明XML配置檔案、Groovy腳本或
@Configuration
類。你還可以自由地使用任何其他測試注解,如
@ActiveProfiles
@Testexecutionlistener
@Sql
@Rollback
和其他。
本節的其餘示例展示了加載
WebApplicationContext
的一些不同配置選項。以下示例顯示了
TestContext
架構對配置約定的支援:
@ExtendWith(SpringExtension.class)
// defaults to "file:src/main/webapp"
@WebAppConfiguration
// detects "WacTests-context.xml" in the same package
// or static nested @Configuration classes
@ContextConfiguration
class WacTests {
//...
}
如果使用
@WebAppConfiguration
注解測試類而未指定資源基本路徑,則資源路徑實際上預設為
file:src/main/webapp
。同樣,如果在聲明
@ContextConfiguration
時未指定資源位置、元件類或上下文初始化程式,則Spring會嘗試使用約定(也就是說,
WacTests-context.xml
WacTests
類或靜态嵌套
@Configuration
類位于同一包中)。
以下示例顯示如何使用
@WebAppConfiguration
顯式聲明資源基本路徑和使用
@ContextConfiguration
顯式聲明XML資源位置:
@ExtendWith(SpringExtension.class)
// file system resource
@WebAppConfiguration("webapp")
// classpath resource
@ContextConfiguration("/spring/test-servlet-config.xml")
class WacTests {
//...
}
這裡要注意的重要一點是具有這兩個注解的路徑的語義不同。預設情況下,
@ WebAppConfiguration
資源路徑基于檔案系統,而
@ContextConfiguration
資源位置基于類路徑。下面的示例顯示,我們可以通過指定Spring資源字首來覆寫兩個注解的預設資源語義:
@ExtendWith(SpringExtension.class)
// classpath resource
@WebAppConfiguration("classpath:test-web-resources")
// file system resource
@ContextConfiguration("file:src/main/webapp/WEB-INF/servlet-config.xml")
class WacTests {
//...
}
将本示例中的注解與上一個示例進行對比。
使用Web Mock工作
為了提供全面的Web測試支援,
TestContext
架構具有預設啟用的
ServletTestExecutionListener
。在針對
WebApplicationContext
進行測試時,此
TestExecutionListener
會在每個測試方法之前使用Spring Web的
RequestContextHolder
來設定預設的線程本地狀态,并根據通過
@WebAppConfiguration
配置的基本資源路徑建立
MockHttpServletRequest
MockHttpServletResponse
ServletWebRequest
ServletTestExecutionListener
還確定可以将
MockHttpServletResponse
ServletWebRequest
注入到測試執行個體中,并且一旦測試完成,它将清除線程本地狀态。
一旦為測試加載了
WebApplicationContext
,你可能會發現你需要與Web模拟進行互動,例如,在調用Web元件之後設定測試
fixture
或執行斷言。以下示例顯示可以将哪些模拟自動裝配到你的測試執行個體。請注意,
WebApplicationContext
MockServletContext
都緩存在測試套件中,而其他模拟則由
ServletTestExecutionListener
針對每個測試方法進行管理。
@SpringJUnitWebConfig
class WacTests {
@Autowired
WebApplicationContext wac; // cached
@Autowired
MockServletContext servletContext; // cached
@Autowired
MockHttpSession session;
@Autowired
MockHttpServletRequest request;
@Autowired
MockHttpServletResponse response;
@Autowired
ServletWebRequest webRequest;
//...
}
一旦
TestContext
架構為測試加載了
ApplicationContext
(或
WebApplicationContext
),該上下文将被緩存并重新用于在同一測試套件中聲明相同唯一上下文配置的所有後續測試。要了解緩存的工作原理,重要的是要了解
unique
測試套件
的含義。
可以通過用于加載它的配置參數的組合來唯一辨別
ApplicationContext
。是以,使用配置參數的唯一組合來生成一個鍵,在該鍵下緩存上下文。
TestContext
架構使用以下配置參數來建構上下文緩存鍵:
-
(來自locations
)@ContextConfiguration
-
classes
@ContextConfiguration
-
contextInitializerClasses
@ContextConfiguration
-
contextCustomizers
)其中包括ContextCustomizerFactory
方法,以及Spring Boot測試支援中的各種功能,例如@DynamicPropertySource
@MockBean
@SpyBean
-
contextLoader
@ContextConfiguration
-
parent
@ContextHierarchy
-
activeProfiles
@ActiveProfiles
-
propertySourceLocations
@TestPropertySource
-
propertySourceProperties
@TestPropertySource
-
resourceBasePath
@WebAppConfiguration
例如,如果
TestClassA
為
@ContextConfiguration
location
value
)屬性指定
{“app-config.xml”,“test-config.xml”}
,則
TestContext
架構将加載相應的
ApplicationContext
并将其存儲在靜态上下文緩存中僅基于那些位置的key下。是以,如果
TestClassB
還為其位置(通過繼承顯式或隐式)定義了
{“app-config.xml”,“test-config.xml”}
,但未定義
@WebAppConfiguration
、不同的
ContextLoader
、不同的激活配置檔案、不同的上下文初始化程式、不同的測試屬性源或不同的父上下文,則兩個測試類将共享相同的
ApplicationContext
。這意味着(每個測試套件)僅需加載一次加載應用程式上下文的設定成本,并且随後的測試執行要快得多。
測試套件和分支流程
Spring
TestContext
架構将應用程式上下文存儲在靜态緩存中。這意味着上下文實際上是存儲在靜态變量中的。換句話說,如果測試是在單獨的程序中執行的,則在每個測試執行之間都會清除靜态緩存,進而有效地禁用了緩存機制。
為了從緩存機制中受益,所有測試必須在同一程序或測試套件中運作。這可以通過在IDE中以組的形式執行所有測試來實作。同樣,在使用諸如Ant、Maven或Gradle之類的建構架構執行測試時,確定該建構架構不會在測試之間進行派生(fork多個程序)很重要。例如,如果将Maven Surefire插件的forkMode設定為always或pertest,則
架構将無法在測試類之間緩存應用程式上下文,是以,建構過程的運作速度将大大降低。
TestContext
上下文緩存的大小以預設的最大32為界。隻要達到最大大小,就會使用最近最少使用(LRU)驅逐政策來驅逐和關閉舊的上下文。你可以通過設定名為
spring.test.context.cache.maxSize
的JVM系統屬性,從指令行或建構腳本中配置最大大小。或者,你可以使用
SpringProperties
API以程式設計方式設定相同的屬性。
由于在給定的測試套件中加載大量的應用程式上下文會導緻該套件花費不必要的長時間來執行,是以準确地知道已加載和緩存了多少個上下文通常是有益的。要檢視基礎上下文緩存的統計資訊,可以将
org.springframework.test.context.cache
日志記錄類别的日志級别設定為
DEBUG
在不太可能的情況下,測試破壞了應用程式上下文并需要重新加載(例如,通過修改bean定義或應用程式對象的狀态),你可以使用
@DirtiesContext
注解測試類或測試方法(請參閱
@DirtiesContext
中對
@DirtiesContext的讨論)。這訓示Spring在運作需要相同應用程式上下文的下一個測試之前,從緩存中删除上下文并重建應用程式上下文。請注意,預設情況下啟用的
DirtiesContextBeforeModesTestExecutionListener
DirtiesContextTestExecutionListener
提供了對
@DirtiesContext
注解的支援。
在編寫依賴于已加載的Spring
ApplicationContext
的內建測試時,通常足以針對單個上下文進行測試。但是,有時需要對
ApplicationContext
執行個體的層次結構進行測試是有益的,甚至是必要的。例如,如果你正在開發Spring MVC Web應用程式,則通常由Spring的
ContextLoaderListener
加載根
WebApplicationContext
,由Spring的
DispatcherServlet
加載子
WebApplicationContext
。這将導緻父子上下文層次結構,其中共享元件和基礎設施配置在根上下文中聲明,并由特定于web的元件在子上下文中使用。在Spring Batch應用程式中可以找到另一個用例,在該應用程式中,你通常具有一個父上下文,該上下文為共享批處理基礎結構提供配置,而子上下文則為特定批處理作業的配置提供配置。
你可以通過在單個測試類上或在測試類層次結構中使用
@ContextHierarchy
注解聲明上下文配置來編寫使用上下文層次結構的內建測試。如果在測試類層次結構中的多個類上聲明了上下文層次結構,則還可以合并或覆寫上下文層次結構中特定命名級别的上下文配置。合并層次結構中給定級别的配置時,配置資源類型(即XML配置檔案或元件類)必須一緻。否則,在使用不同資源類型配置的上下文層次結構中具有不同級别是完全可以接受的。
本節中其餘的基于JUnit Jupiter的示例顯示了需要使用上下文層次結構的內建測試的常見配置方案。
具有上下文層次結構的單個測試類
ControllerIntegrationTests
通過聲明一個上下文層次結構來代表Spring MVC Web應用程式的典型內建測試場景,該上下文層次結構包含兩個級别,一個層次用于根
WebApplicationContext
(通過使用
TestAppConfig
@Configuration類加載),一個層次用于排程程式Servlet
WebApplicationContext
WebConfig
@Configuration
類加載)。自動裝配到測試執行個體的
WebApplicationContext
是用于子上下文(即,層次結構中的最低上下文)的
WebApplicationContext
以下清單顯示了此配置方案:
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration(classes = TestAppConfig.class),
@ContextConfiguration(classes = WebConfig.class)
})
class ControllerIntegrationTests {
@Autowired
WebApplicationContext wac;
// ...
}
org.liyong.test.annotation.test.spring.ControllerIntegrationTests
具有隐式父上下文的類層次結構
本示例中的測試類在測試類層次結構中定義了上下文層次結構。
AbstractWebTests
在Spring驅動的Web應用程式中聲明根
WebApplicationContext
的配置。但是請注意,
AbstractWebTests
不會聲明
@ContextHierarchy
AbstractWebTests
的子類可以選擇參與上下文層次結構或遵循
@ContextConfiguration
的标準語義。
SoapWebServiceTests
RestWebServiceTests
都擴充了
AbstractWebTests
@ContextHierarchy
定義了上下文層次結構。結果是,加載了三個應用程式上下文(每個
@ContextConfiguration
聲明一個),并且基于
AbstractWebTests
中的配置加載的應用程式上下文被設定為具體子類加載的每個上下文的父上下文。
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
public abstract class AbstractWebTests {}
@ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml"))
public class SoapWebServiceTests extends AbstractWebTests {}
@ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml"))
public class RestWebServiceTests extends AbstractWebTests {}
org.liyong.test.annotation.test.spring.RestWebServiceTests
合并上下文層次結構配置的類層次結構
此示例中的類顯示了使用命名層次結構級别的目的,以及合并上下文層次結構中特定級别的配置。
BaseTests
在層次結構中定義了兩個級别,
parent
child
ExtendedTests
擴充
BaseTests
并訓示Spring
TestContext
架構合并子層次結構級别的上下文配置,方法是確定在
@ContextConfiguration
的name屬性中聲明的名稱均為子元素。結果是加載了三個應用程式上下文:一個用于
/app-config.xml
、一個用于
/user-config.xml
{/user-config.xml
,
/order-config.xml}
。與前面的示例一樣,将從
/app-config.xml
加載的應用程式上下文設定為從
/user-config.xml
{“/user-config.xml","/order-config.xml“}
加載的上下文的父上下文(合并配置檔案)。以下清單顯示了此配置方案:
@ExtendWith(SpringExtension.class)
@ContextHierarchy({
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}
@ContextHierarchy(
@ContextConfiguration(name = "child", locations = "/order-config.xml")
)
class ExtendedTests extends BaseTests {}
org.liyong.test.annotation.test.spring.ExtendedTests
具有覆寫的上下文層次結構配置的類層次結構
與前面的示例相反,此示例示範了如何通過将
@ContextConfiguration
InheritLocations
标志設定為
false
來覆寫上下文層次結構中給定命名級别的配置。是以,
ExtendedTests
的應用程式上下文僅從
/test-user-config.xml
加載,并且其父級設定為從
/app-config.xml
加載的上下文。以下清單顯示了此配置方案:
@ExtendWith(SpringExtension.class)
@ContextHierarchy({
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
@ContextConfiguration(name = "child", locations = "/user-config.xml")
})
class BaseTests {}
@ContextHierarchy(
@ContextConfiguration(
name = "child",
locations = "/test-user-config.xml",
inheritLocations = false
))
class ExtendedTests extends BaseTests {}
清除上下文層次結構中的上下文
如果你在一個測試中使用@DirtiesContext,該測試的上下文被配置為上下文層次結構的一部分,那麼你可以使用hierarchyMode标志來控制如何清除上下文緩存。有關更多詳細資訊,請參見
Spring Testing Annotations 中的@DirtiesContext和 javadoc的讨論。
org.liyong.test.annotation.test.spring.ExtendedTests1
3.5.6 測試裝置的依賴注入
當使用
DependencyInjectionTestExecutionListener
(預設配置)時,測試執行個體的依賴項是從使用
@ContextConfiguration
或相關注解配置應用程式上下文中的bean注入的。你可以使用
setter
注入、字段注入、或同時使用這兩種方法,具體取決于你選擇的注解以及是否将它們放在
setter
方法或字段上。如果你使用的是JUnit Jupiter,則還可以選擇使用構造函數注入(請參閱帶有
SpringExtension的依賴注入)。為了與Spring基于注解的注入支援保持一緻,你還可以将Spring的
@Autowired
注解或JSR-330中的
@Inject
注解用于字段注入和setter 注入。
對于JUnit Jupiter以外的測試架構,架構不參與測試類的執行個體化。是以,将
TestContext
@Autowired
@Inject
用于構造函數對測試類無效。
盡管在生産代碼中不鼓勵使用字段注入,但是在測試代碼中字段注入實際上是很自然的。理由是你永遠不會直接執行個體化測試類。是以,不需要在測試類上調用公共構造函數或
方法。
setter
因為
@Autowired
用于按類型執行自動裝配,是以如果你具有多個相同類型的Bean定義,那麼對于那些特定的Bean,你将不能依靠這種方法。在這種情況下,可以将
@Autowired
@Qualifier
結合使用。你也可以選擇将
@Inject
@Named
結合使用。或者,如果你的測試類可以通路其
ApplicationContext
,則可以通過使用(例如)對
applicationContext.getBean(“ titleRepository“,TitleRepository.class)
的調用來執行顯式查找。
如果你不希望将依賴項注入應用于測試執行個體,請不要使用
@Autowired
@Inject
注解字段或設定器方法。或者,你可以通過顯式地用
@TestExecutionListeners
配置你的類,并從監聽器清單中忽略
DependencyInjectionTestExecutionListener.class
來禁用依賴注入。
考慮測試
HibernateTitleRepository
類的場景,如
目标部分所述。接下來的兩個代碼清單示範了
@Autowired
在字段和
setter
方法上的用法。在所有示例代碼清單之後顯示了應用程式上下文配置。
以下代碼清單中的依賴項注入行為并非特定于JUnit Jupiter。相同的
DI
技術可以與任何受支援的測試架構結合使用。
以下示例對靜态斷言方法(例如
)進行了調用,但沒有在聲明前添加
assertNotNull()
。在這種情況下,假定該方法是通過示例中未顯示的
Assertions
聲明正确導入的。
import static
第一個代碼清單顯示了使用
@Autowired
進行字段注入的測試類的基于JUnit Jupiter的實作:
@ExtendWith(SpringExtension.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// this instance will be dependency injected by type
@Autowired
HibernateTitleRepository titleRepository;
@Test
void findById() {
Title title = titleRepository.findById(new Long(10));
assertNotNull(title);
}
}
或者,你可以将類配置為使用
@Autowired
進行
setter
注入,如下所示:
@ExtendWith(SpringExtension.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// this instance will be dependency injected by type
HibernateTitleRepository titleRepository;
@Autowired
void setTitleRepository(HibernateTitleRepository titleRepository) {
this.titleRepository = titleRepository;
}
@Test
void findById() {
Title title = titleRepository.findById(new Long(10));
assertNotNull(title);
}
}
前面的代碼清單使用
@ContextConfiguration
注解引用的相同XML上下文檔案(即,
repository-config.xml
)。下面顯示了此配置:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- this bean will be injected into the HibernateTitleRepositoryTests class -->
<bean id="titleRepository" class="com.foo.repository.hibernate.HibernateTitleRepository">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- configuration elided for brevity -->
</bean>
</beans>
如果你是從Spring提供的測試基類擴充而來的,而該基類恰巧在其方法之一上使用
setter
,則可能在應用程式上下文中定義了多個受影響類型的Bean(例如,多個
@Autowired
Bean)。在這種情況下,你可以覆寫setter方法,并使用
DataSource
注解訓示特定的目标bean,如下所示(但請確定也委托給超類中的重寫方法):
@Qualifier
指定的限定符值訓示要注入的特定// ... @Autowired @Override public void setDataSource(@Qualifier("myDataSource") DataSource dataSource) { super.setDataSource(dataSource); } // ...
Bean,進而将類型比對的範圍縮小到特定Bean。其值與相應的定義中的聲明比對。Bean名稱用作後備限定符值,是以你也可以在該名稱中有效地指向特定的Bean(如先前所示,假設
DataSource
是Bean
myDataSource
ID
作者
個人從事金融行業,就職過易極付、思建科技、某網約車平台等重慶一流技術團隊,目前就職于某銀行負責統一支付系統建設。自身對金融行業有強烈的愛好。同時也實踐大資料、資料存儲、自動化內建和部署、分布式微服務、響應式程式設計、人工智能等領域。同時也熱衷于技術分享創立公衆号和部落格站點對知識體系進行分享。關注公衆号:青年IT男 擷取最新技術文章推送!
部落格位址:
http://youngitman.techCSDN:
https://blog.csdn.net/liyong1028826685微信公衆号:

技術交流群: