Dependency Injection of Test Fixtures
当你使用 DependencyInjectionTestExecutionListener
时(默认配置),测试实例的依赖关系会从使用 @ContextConfiguration
或相关注释配置的应用程序上下文中注入 bean。你可以使用设置器注入、字段注入,或同时使用这两种方式,这取决于你选择哪些注释以及你是不是将它们放在设置器方法或字段上。如果你使用 JUnit Jupiter,你还可以选择使用构造函数注入(请参阅 Dependency Injection with SpringExtension
)。为了与 Spring 的基于注释的注入支持保持一致,你还可以对字段和设置器注入使用 Spring 的 @Autowired
注释或 JSR-330 的 @Inject
注释。
对于除 JUnit Jupiter 之外的测试框架,TestContext 框架不参与测试类的实例化。因此,在构造函数中使用 |
尽管在生产代码中不鼓励字段注入,但字段注入实际上在测试代码中非常自然。这种差异的原理是你将永远不会直接实例化你的测试类。因此,不需要能够在你的测试类上调用 |
因为 @Autowired
用于执行 autowiring by type,所以如果您有多个相同类型的 bean 定义,您无法对这些特定 bean 使用此方法。在这种情况下,您可以将 @Autowired
与 @Qualifier
结合使用。您也可以选择将 @Inject
与 @Named
结合使用。或者,如果您的测试类可以访问其 ApplicationContext
,您可以通过使用(例如)调用 applicationContext.getBean("titleRepository", TitleRepository.class)
来执行显式查找。
如果您不希望将依赖注入应用于测试实例,请不要使用 @Autowired
或 @Inject
注释字段或 setter 方法。或者,您可以通过使用 @TestExecutionListeners
显式配置类并从监听器列表中省略 DependencyInjectionTestExecutionListener.class
来完全禁用依赖注入。
考虑在Goals 部分中概述的测试 HibernateTitleRepository
类的场景。接下来两个代码清单演示了在字段和设置器方法上使用 @Autowired
。应用程序上下文配置在所有示例代码清单之后呈现。
以下代码列表中的依赖注入行为不特定于 JUnit Jupiter。相同的 DI 技术可以与任何受支持的测试框架结合使用。
以下示例调用静态断言方法,例如 |
第一个代码列表显示了使用 @Autowired
进行字段注入的 JUnit Jupiter 的基于实现的测试类:
-
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
注释(即 repository-config.xml
)引用的同一个 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 方法上使用 |
- Java
-
// ... @Autowired @Override public void setDataSource(@Qualifier("myDataSource") DataSource dataSource) { super.setDataSource(dataSource); } // ...
- Kotlin
-
// ... @Autowired override fun setDataSource(@Qualifier("myDataSource") dataSource: DataSource) { super.setDataSource(dataSource) } // ...
指定限定符值表示要注入的特定 DataSource
Bean,这将类型匹配集缩小到特定 Bean。其值与相应 <bean>
定义中的 <qualifier>
声明匹配。Bean 名称用作备用限定符值,因此您实际上也可以通过名称指向特定 Bean(如先前所示,假定 myDataSource
是 Bean id
)。