測試夾具的依賴注入
當您使用 DependencyInjectionTestExecutionListener(預設已配置)時,測試例項的依賴項將從您使用 @ContextConfiguration 或相關注解配置的應用程式上下文中的 bean 中注入。您可以根據選擇的註解以及是否將其放置在 setter 方法或欄位上來使用 setter 注入、欄位注入或兩者。如果您使用的是 JUnit Jupiter,您還可以選擇使用建構函式注入(請參閱 使用 SpringExtension 進行依賴注入)。為了與 Spring 的基於註解的注入支援保持一致,您還可以使用 Spring 的 @Autowired 註解或 JSR-330 的 @Inject 註解進行欄位和 setter 注入。
對於除 JUnit Jupiter 之外的測試框架,TestContext 框架不參與測試類的例項化。因此,@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。應用程式上下文配置將在所有示例程式碼列表之後呈現。
|
以下程式碼列表中的依賴注入行為並非 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 上下文檔案(即 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.jpa.hibernate.LocalSessionFactoryBean">
<!-- configuration elided for brevity -->
</bean>
</beans>
|
如果您正在擴充套件 Spring 提供的測試基類,該基類恰好在其某個 setter 方法上使用了
指定的限定符值指示要注入的特定 |