测试固件的依赖注入
当您使用DependencyInjectionTestExecutionListener
(默认配置)时,您的测试实例的依赖项将从应用程序上下文中的bean中注入,您可以使用@ContextConfiguration
或相关注解配置该应用程序上下文。您可以根据选择的注解以及将它们放置在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)
// 指定要加载的Spring配置以用于此测试固件
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// 此实例将按类型进行依赖注入
@Autowired
HibernateTitleRepository titleRepository;
@Test
void findById() {
Title title = titleRepository.findById(new Long(10));
assertNotNull(title);
}
}
@ExtendWith(SpringExtension::class)
// 指定要加载的Spring配置以用于此测试固件
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// 此实例将按类型进行依赖注入
@Autowired
lateinit var titleRepository: HibernateTitleRepository
@Test
fun findById() {
val title = titleRepository.findById(10)
assertNotNull(title)
}
}
或者,您可以配置类使用@Autowired
进行setter注入,如下所示:
-
Java
-
Kotlin
@ExtendWith(SpringExtension.class)
// 指定要加载的Spring配置以用于此测试固件
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// 此实例将按类型进行依赖注入
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)
// 指定要加载的Spring配置以用于此测试固件
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// 此实例将按类型进行依赖注入
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">
<!-- 此bean将被注入到HibernateTitleRepositoryTests类中 -->
<bean id="titleRepository" class="com.foo.repository.hibernate.HibernateTitleRepository">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 为简洁起见省略了配置 -->
</bean>
</beans>
如果您正在扩展Spring提供的测试基类,该基类恰好在其中一个setter方法上使用了
指定的限定符值指示要注入的特定 |