Java JUnit测试中的嵌套自动连线不工作

Java JUnit测试中的嵌套自动连线不工作,java,spring,junit,jdbctemplate,spring-annotations,Java,Spring,Junit,Jdbctemplate,Spring Annotations,我正在使用JavaFX开发一个spring应用程序(我不是使用springmvc,而是),我对控制器-服务-dao有标准的关注点分离。我正在使用JdbcTemplate。我愿意为我的一项服务编写jUnit测试(我已经为其中一些服务编写了测试)。具体来说,该服务自动连接两个DAO(其中一个使用事务本身),而且它还有一个方法,即@Transactional。我的测试就是这样的: package org.impactvolunteers.management.service.impl; import

我正在使用JavaFX开发一个spring应用程序(我不是使用springmvc,而是),我对控制器-服务-dao有标准的关注点分离。我正在使用JdbcTemplate。我愿意为我的一项服务编写jUnit测试(我已经为其中一些服务编写了测试)。具体来说,该服务自动连接两个DAO(其中一个使用事务本身),而且它还有一个方法,即
@Transactional
。我的测试就是这样的:

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);
    }

}
以及我的服务实施:

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);
        }
    }
}
在应用程序上下文中:

<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>

...
以下是错误消息:

org.springframework.beans.factory.BeanCreationException:创建名为的bean时出错 “org.impact志愿人员.管理.service.impl.RegisterVolunterServiceImpltest”: 自动连线依赖项的注入失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法 自动连线字段:专用 org.impact志愿者。管理。服务。注册志愿者服务 org.impact.management.service.impl.RegisterVolunterServiceImpltest.RegisterVolunterService; 嵌套异常是 org.springframework.beans.factory.noSuchBean定义异常:否 类型的限定bean [org.impactVolumers.management.service.RegisterVolunterService] 为依赖项找到:至少需要1个符合以下条件的bean 此依赖项的自动连线候选项。依赖项批注: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 位于org.springframework.beans.factory.annotation.AutoWiredNotationBeanPostProcessor.postProcessPropertyValues(AutoWiredNotationBeanPostProcessor.java:288) ............ 原因:org.springframework.beans.factory.NoSuchBean定义异常:否 类型的限定bean [org.impactVolumers.management.service.RegisterVolunterService] 为依赖项找到:至少需要1个符合以下条件的bean 此依赖项的自动连线候选项。依赖项批注: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 位于org.springframework.beans.factory.support.DefaultListableBeanFactory.RaiseNouchBeanDefinitionException(DefaultListableBeanFactory.java:988) 位于org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858) 位于org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) 位于org.springframework.beans.factory.annotation.AutoWiredNotationBeanPostProcessor$AutoWiredFeldElement.inject(AutoWiredNotationBeanPostProcessor.java:486) ... 28多

和我的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"/>

我注意到两件奇怪的事:

  • 我可以将应用程序作为Java应用程序启动,并且服务可以按预期工作。作为jUnit测试,我只在测试服务时遇到问题
  • 一个具有完全相同的上下文(以及与此处显示的测试相同的测试上下文)和bean定义的服务正在成功地进行测试,唯一的区别是它不包含
    @Transactional
    注释,而它下面的一些DAO是这样做的(
    autonovatedaoimpl
    实现了
    autonovatedao
    但包含了
    @Transactional
    注释)

  • testContext.xml
    不会导入通用应用程序上下文,也不会定义
    RegisterVolunterService
    bean。

    RegisterVolunterServiceImpl
    必须注释为服务

    如果类没有被注释为服务,那么组件扫描将不会找到它。因此,名为的bean没有实例化,不能自动连接

    在主应用程序上下文中,添加bean而不进行组件扫描

     <bean id="registerVolunteerService" class="org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImpl" >
        </bean>
    
    
    
    类RegisterVolunterServiceImpl必须被注释为服务。是的,它起作用了。你能解释一下为什么在这种情况下会这样吗?是的,我会给它写一个答案,这样如果它是你的解决方案,你就可以接受它。这不是问题,因为添加服务注释修复了它,其他测试用例也按预期工作。这是实际上是问题所在,因为您只是让Spring以不同的方式创建bean(这次是组件扫描)。因此,您也可以从常规XML上下文中删除bean声明。我想我现在明白了。在作为普通应用程序启动它时发现它的原因是,它在applicationContext中定义为bean,但当我作为jUnit测试启动它时,必须对其进行扫描,但没有@Service注释,它不是被找到了,对吗?如果这是对的,那么留给我的问题是,为什么在测试时我的其他未注释服务被找到了,而这个特定的服务没有被找到?正如我所说的,我注意到的唯一的一般区别是这个服务有一个事务方法。@IvayloToskov-Spring可以通过扫描找到您的bean,这需要
    @Component
    或其子注释之一,如
    @Service
    ,或通过专门配置它。至于为什么某些组件会在测试上下文中加载,如果没有完整的配置是不可能知道的。因此,您能否解释一下,当作为普通Java应用程序启动应用程序时,如何找到该服务?为什么会这样我的其他服务在它们的测试用例中被发现,但它们没有被注释为服务?你不应该有一个完整的测试上下文,你应该只覆盖需要不同或添加的bean。接下来加载普通上下文文件和修改的测试上下文(可能只包含
    数据源
    ,也可能包含
    JdbcTemplate
    )。