測試裝置的依賴注入
當您使用 DependencyInjectionTestExecutionListener
(預設已組態) 時,測試實例的依賴性會從應用程式 Context 中的 Bean 注入,這些 Bean 是您使用 @ContextConfiguration
或相關註解所組態的。您可以根據您選擇的註解以及是否將它們放在 setter 方法或欄位上,使用 setter 注入、欄位注入或兩者兼具。如果您使用的是 JUnit Jupiter,您也可以選擇性地使用建構子注入 (請參閱 使用 SpringExtension
的依賴注入)。為了與 Spring 基於註解的注入支援保持一致,您也可以使用 Spring 的 @Autowired
註解或 JSR-330 的 @Inject
註解進行欄位和 setter 注入。
對於 JUnit Jupiter 以外的測試框架,TestContext framework 不參與測試類別的實例化。因此,對於測試類別,使用 @Autowired 或 @Inject 於建構子沒有任何效果。 |
雖然不鼓勵在生產程式碼中使用欄位注入,但欄位注入在測試程式碼中實際上非常自然。差異的理由是您永遠不會直接實例化您的測試類別。因此,無需能夠在您的測試類別上調用 public 建構子或 setter 方法。 |
由於 @Autowired
用於執行依類型自動裝配,如果您有多個相同類型的 Bean 定義,您就不能依賴這種方法來處理這些特定的 Bean。在這種情況下,您可以將 @Autowired
與 @Qualifier
結合使用。您也可以選擇將 @Inject
與 @Named
結合使用。或者,如果您的測試類別可以存取其 ApplicationContext
,您可以使用 (例如) 調用 applicationContext.getBean("titleRepository", TitleRepository.class)
來執行顯式查找。
如果您不希望將依賴注入應用於您的測試實例,請勿使用 @Autowired
或 @Inject
註解欄位或 setter 方法。或者,您可以透過使用 @TestExecutionListeners
顯式組態您的類別,並從監聽器列表中省略 DependencyInjectionTestExecutionListener.class
,來完全停用依賴注入。
考慮測試 HibernateTitleRepository
類別的場景,如目標章節中所概述。接下來的兩個程式碼清單示範了在欄位和 setter 方法上使用 @Autowired
。應用程式 Context 組態在所有範例程式碼清單之後呈現。
以下程式碼清單中的依賴注入行為並非 JUnit Jupiter 特有。相同的 DI 技術可以與任何支援的測試框架結合使用。 以下範例調用了靜態斷言方法,例如 |
第一個程式碼清單顯示了基於 JUnit Jupiter 的測試類別實作,該實作使用 @Autowired
進行欄位注入
-
Java
-
Kotlin
@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);
}
}
@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
lateinit var titleRepository: HibernateTitleRepository
@Test
fun findById() {
val title = titleRepository.findById(10)
assertNotNull(title)
}
}
或者,您可以組態類別以使用 @Autowired
進行 setter 注入,如下所示
-
Java
-
Kotlin
@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);
}
}
@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
lateinit var titleRepository: HibernateTitleRepository
@Autowired
fun setTitleRepository(titleRepository: HibernateTitleRepository) {
this.titleRepository = titleRepository
}
@Test
fun findById() {
val title = titleRepository.findById(10)
assertNotNull(title)
}
}
前面的程式碼清單使用 @ContextConfiguration
註解引用的相同 XML Context 檔案 (即 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 方法之一上使用了
指定的限定詞值指示要注入的特定 |