简体   繁体   中英

Nested autowiring in JUnit test not working

I'm developing a spring application using JavaFX (I'm NOT using Spring MVC) and I have standard separation of concerns with controllers - services - DAOs. I'm using JdbcTemplate. I'm willing to write down jUnit tests for one of my services (I have already did it for some of them). The specific thing is that the service is autowiring two DAOs(one of which uses transactions itself) and furthermore it has one method, which is @Transactional . This is how my test exactly looks:

package org.impactvolunteers.management.service.impl;

imports ...;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:testContext.xml" })
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class RegisterVolunteerServiceImplTest extends
        AbstractRegisterVolunteerServiceTest {
    @Autowired
    private RegisterVolunteerService registerVolunteerService;

    @Before
    public void setUp() {
        setRegisterVolunteerService(registerVolunteerService);
    }

}

And my Service implementation:

package org.impactvolunteers.management.service.impl;

imports ...;

public class RegisterVolunteerServiceImpl implements RegisterVolunteerService {
    @Autowired
    private VolunteerDao volunteerDao;

    @Autowired
    private UserDao userDao;

    @Transactional(rollbackFor = { ServiceException.class,
            ValidationException.class })
    public Volunteer registerVolunteer(User user, Volunteer volunteer)
            throws ServiceException, ValidationException {
        UserValidator.validateData(user);
        VolunteerValidator.validateData(volunteer);
        try {
            User ret = userDao.create(user);
            volunteer.setUser(ret);
            return volunteerDao.create(volunteer);
        } catch (PersistenceException e) {
            throw new ServiceException(e.getMessage(), e);
        }
    }
}

And in application-Context:

<context:component-scan base-package="org.impactvolunteers.management"/>

    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

    <!-- Transaction Manager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    ...
    <bean id="registerVolunteerService" class="org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImpl" >
    </bean>

Here is the error message:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImplTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.impactvolunteers.management.service.RegisterVolunteerService org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImplTest.registerVolunteerService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.impactvolunteers.management.service.RegisterVolunteerService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288) ............ Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.impactvolunteers.management.service.RegisterVolunteerService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) ... 28 more

And my test-Context.xml:

    <context:annotation-config/>

    <context:component-scan base-package="org.impactvolunteers.management"/>

    <bean id="jdbc" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- Spring JDBC Utility for in-memory database -->
    <jdbc:embedded-database id="dataSource" type="HSQL"/>

Two strange things I noticed:

  1. I have no problem starting the application as Java application and the service works as intended. I have only problems testing the service as jUnit test.
  2. A service with the exact same context (and the same context for the test as the test showed here) and bean definition is being successfully tested with the only difference that it does not contain @Transactional annotations, where some of the DAOs under it do ( VolunteerDaoImpl which implements VolunteerDao does contain a @Transactional annotation).

The class RegisterVolunteerServiceImpl must be annotated as service.

If the class is not annotated as a service it will not befound by the component-scan. So the bean with the name is not instanciated and can not be autowired.

In your main application-context you add the bean without component-scan

 <bean id="registerVolunteerService" class="org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImpl" >
    </bean>

testContext.xml不会导入您的通用应用程序上下文,也不会定义该registerVolunteerService bean。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM