測試夾具的依賴注入
當你使用 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)
。
如果你不希望對你的測試例項應用依賴注入,請不要在欄位或 Setter 方法上使用 @Autowired
或 @Inject
註解。或者,你可以透過使用 @TestExecutionListeners
顯式配置你的類,並從 Listener 列表中省略 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.hibernate5.LocalSessionFactoryBean">
<!-- configuration elided for brevity -->
</bean>
</beans>
如果你從一個恰好在其 Setter 方法上使用
指定的限定符值指示要注入的特定 |