If you use the DependencyInjectionTestExecutionListener
(which is configured by default), your test
instances' dependencies are injected from beans in the application context that you configured using the @ContextConfiguration
annotation or related annotations . You can use setter dependency injection, field dependency injection, or both,
depending on which annotations you choose and whether you place them in setters or fields. If you are using JUnit
Jupiter, you can also optionally use constructor injection (see "Dependency
Injection with SpringExtension"
). For consistency with Spring's annotation-based dependency
injection support, you can also use the @Autowired
annotation or the @Inject
annotation
from JSR-330 to perform dependency injection via field and setter.
@Autowired
or @Inject
annotation on constructors has no effect on test classes.
public
constructor or setter in your test class.
Because the @Autowired
annotation is used to perform automatic
detection and linking by typeif you have multiple bean definitions of the same type, you won't be able to use
this approach for those specific beans. In this case, you can use the @Autowired
annotation in
combination with the @Qualifier
annotation. You can also use the @Inject
annotation in
combination with the @Named
annotation. Additionally, if your test class has access to its ApplicationContext
,
you can perform an explicit sequential lookup using (for example) calling applicationContext.getBean("titleRepository",
TitleRepository.class)
.
If you need dependency injection to be applied to your test instances, do not annotate fields or setters with the
@Autowired
annotation or the @Inject
annotation. Alternatively, you can disable dependency
injection entirely by explicitly configuring your class to use the @TestExecutionListeners
annotation
and excluding DependencyInjectionTestExecutionListener.class
from the list of listeners.
Consider the testing scenario for the HibernateTitleRepository
class, as described in the section
"Goals". The following two code listings demonstrate the use of the @Autowired
annotation for
fields and setters. The application context configuration is presented after all example code listings.
The dependency injection logic in the following code listings is not specific to JUnit Jupiter. The same dependency injection techniques can be used in combination with any supported testing framework.
The following examples call static methods with an assertion, such as assertNotNull()
, but without
first calling Assertions
. In such cases, assume that the method was properly imported via an import
static
declaration, which is not shown in the example.
The first code listing shows an implementation of a JUnit Jupiter-based test class that uses the
@Autowired
annotation for dependency injection via a field:
@ExtendWith(SpringExtension.class)
// defines the loaded Spring configuration for this testbench
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// this instance will be injected with a dependency by type
@Autowired
HibernateTitleRepository titleRepository;
@Test
void findById() {
Title title = titleRepository.findById(new Long(10));
assertNotNull(title);
}
}
@ExtendWith(SpringExtension::class)
// defines the loaded Spring configuration for this testbench
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// this instance will be injected with a dependency by type
@Autowired
lateinit var titleRepository: HibernateTitleRepository
@Test
fun findById() {
val title = titleRepository.findById(10)
assertNotNull(title)
}
}
Alternatively, you can configure the class to use the @Autowired
annotation for dependency injection via
a setter, as shown below:
@ExtendWith(SpringExtension.class)
// defines the loaded Spring configuration for this testbench
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// this instance will be injected with a dependency 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)
// defines the loaded Spring configuration for this testbench
@ContextConfiguration("repository-config.xml")
class HibernateTitleRepositoryTests {
// this instance will be injected with a dependency by type
lateinit var titleRepository: HibernateTitleRepository
@Autowired
fun setTitleRepository(titleRepository: HibernateTitleRepository) {
this.titleRepository = titleRepository
}
@Test
fun findById() {
val title = titleRepository.findById(10)
assertNotNull(title)
}
}
The previous code listings use the same XML context file referenced by the @ContextConfiguration
annotation (that is, repository-config.xml
). This configuration is shown below:
<?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 omitted for the sake of brevity -->
</bean>
</beans>
If you extend a main test class provided by Spring that uses the @Autowired
annotation in one of its
setters, you may have multiple beans of the corresponding type defined in your application context (for example,
multiple beans DataSource
). In this case, you can override the setter and use the
@Qualifier
annotation to specify a specific target bean, as shown below (but be sure to also
delegate to the overridden method in the superclass):
// ...
@Autowired
@Override
public void setDataSource(@Qualifier("myDataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}
// ...
// ...
@Autowired
override fun setDataSource(@Qualifier("myDataSource") dataSource: DataSource) {
super.setDataSource(dataSource)
}
// ...
The specified qualifier value points to the specific DataSource
bean to be injected, narrowing the
set of type matches to the specific bean. Its value is matched against <qualifier>
declarations in corresponding <bean>
definitions. The bean name is used as the return value
of the qualifier so that a specific bean can be properly referenced by name (as shown earlier, assuming myDataSource
is the id
of the bean).