I ran into a problem that can only be explained by my fundamental lack of understanding IoC containers and setting up the Spring context, so I will ask for clarification on this.
For reference, the application that I support has the following technology stack:
- Java 1.6
- Spring 2.5.6
- Interface RichFaces 3.3.1-GA Structure
- Spring is used to control beans using the Spring JDBC module used to support DAO
- Maven is used as a build manager
- JUnit 4.4 is now introduced as a test engine
I retroactively (sic!) Write JUnit tests for the application, and what amazes me is that I could not inject the bean into the test class using setter injection without resorting to @Autowire notation.
Let me give an example and the accompanying configuration files.
The test class is TypeTestreally simple:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TypeTest {
@Autowired
private IType type;
@Test
public void testFindAllTypes() {
List<Type> result;
try {
result = type.findAlltTypes();
assertNotNull(result);
} catch (Exception e) {
e.printStackTrace();
fail("Exception caught with " + e.getMessage());
}
}
}
Its context is defined in TestStackOverflowExample-context.xml:
<context:property-placeholder location="classpath:testContext.properties" />
<context:annotation-config />
<tx:annotation-driven />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.connection.driver.class}" />
<property name="url" value="${db.connection.url}" />
<property name="username" value="${db.connection.username}" />
<property name="password" value="${db.connection.password}" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="beanDAO" class="com.example.BeanDAOImpl">
<property name="ds" ref="dataSource"></property>
<property name="beanDAOTwo" ref="beanDAOTwo"></property>
</bean>
<bean id="beanDAOTwo" class="com.example.BeanDAOTwoImpl">
<property name="ds" ref="dataSource"></property>
</bean>
<bean id="type" class="com.example.TypeImpl">
<property name="beanDAO" ref="beanDAO"></property>
</bean>
TestContext.properties is on the class path and contains only db specific data needed for the data source.
This works like a charm, but my question is: why doesn't it work when I try to manually connect the beans and complete the installation installation, as in:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TypeTest {
private IType type;
public IType getType () {
return type;
}
public void setType(IType type) {
this.type= type;
}
@Test
public void testFindAllTypes(){
}
}
What am I missing here? What part of the configuration is wrong here? When I try to manually enter beans through the setters, the test fails because this part
result = type.findAlltTypes();
null . , , Spring XML; , , , Spring beans, - Spring Test Context, @Autowired , , , JavaDoc Autowired, PostProcessor .
, @Autowired . , : , , ? DI ? @Autowired Spring ?
EDIT:
, :
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TypeTest implements ApplicationContextAware{
private IType type;
private ApplicationContext ctx;
public TypeTest(){
super();
ctx = new FileSystemXmlApplicationContext("/TypeTest-context.xml");
ctx.getBean("type");
}
public IType getType () {
return type;
}
public void setType(IType type) {
this.type= type;
}
@Test
public void testFindAllTypes(){
}
}
, ?
EDIT2:
, TestContextListener BeanPostProcessor. , , :
1) :
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TypeTest{
private IType type;
private ApplicationContext ctx;
public TypeTest(){
super();
ctx = new FileSystemXmlApplicationContext("/TypeTest-context.xml");
type = ctx.getBean("type");
}
public IType getType () {
return type;
}
public void setType(IType type) {
this.type= type;
}
@Test
public void testFindAllTypes(){
}
}
2) ApplicationContextAware:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TypeTest implements ApplicationContextAware{
private IType type;
private ApplicationContext ctx;
public IType getType () {
return type;
}
public void setType(IType type) {
this.type= type;
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.ctx = ctx;
type = (Type) ctx.getBean("type");
}
@Test
public void testFindAllTypes(){
}
}
beans.