SessionFactory не получает автоподключение при попытке модульного тестирования класса DAO

Я застрял в странной ситуации, когда определенная мной sessionFactory автоматически подключается к классу DAO, когда я запускаю ее как веб-приложение.

Однако, когда я пытаюсь выполнить модульное тестирование этого класса DAO, Spring не выполняет автоматическую привязку sessionFactory к классу DAO и не выдает приведенное ниже исключение.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'activityDAO': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.adwitiya.vdb.data.activity.ActivityDAO.sessionFactory; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.hibernate.SessionFactory] 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:287)   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)   at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)   at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)  at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)     at com.adwitiya.vdb.data.activity.ActivityDAOTest.testConstructor(ActivityDAOTest.java:31)  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    at java.lang.reflect.Method.invoke(Method.java:601)     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)   at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)     at org.junit.runners.ParentRunner.run(ParentRunner.java:300)    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)  at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    at java.lang.reflect.Method.invoke(Method.java:601)     at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)   at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)  at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)  at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68) Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.adwitiya.vdb.data.activity.ActivityDAO.sessionFactory; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.hibernate.SessionFactory] 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$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)   ... 41 more Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.hibernate.SessionFactory] 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:952)     at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)    ... 43 more

Я чертовски много гуглил, но не смог найти решение этой проблемы. Я был бы очень рад и благодарен, если бы вы могли мне помочь.

Вот мои файлы конфигурации и классов.

Web.xml
-------
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app
vdb-servlet.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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/lang
        http://www.springframework.org/schema/lang/spring-lang-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.1.xsd">

    <mvc:resources mapping="/skin/**" location="/skin/" />

    <context:annotation-config />
    <context:component-scan base-package="com.adwitiya.vdb" />

    <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
                  value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <mvc:annotation-driven />

</beans>
0.xsd" version="3.0"> <session-config> <session-timeout> 30 </session-timeout> </session-config> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/vdb-data.xml </param-value> </context-param> <filter> <filter-name>hibernateFilter</filter-name> <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </filter-class> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>vdb</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>vdb</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file></welcome-file> </welcome-file-list> </web-app>

Мой основной файл конфигурации MVC приведен ниже.

vdb-servlet.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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/lang
        http://www.springframework.org/schema/lang/spring-lang-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.1.xsd">

    <mvc:resources mapping="/skin/**" location="/skin/" />

    <context:annotation-config />
    <context:component-scan base-package="com.adwitiya.vdb" />

    <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
                  value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <mvc:annotation-driven />

</beans>

Ниже приведен файл конфигурации Spring, связанный с базой данных

vdb-data.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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/lang
        http://www.springframework.org/schema/lang/spring-lang-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.1.xsd">

    <bean id="messageSource"
          class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>

    <context:property-placeholder location="classpath:database.properties" />

    <tx:annotation-driven transaction-manager="hibernateTransactionManager"/>

    <bean id="dataSource"
              class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${database.driver}" />
        <property name="url" value="${database.url}" />
        <property name="username" value="${database.user}" />
        <property name="password" value="${database.password}" />
    </bean>

    <bean id="sessionFactory"
              class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.adwitiya.vdb.domain" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.c3p0.min_size">${hibernate.c3p0.min_size}</prop>
                <prop key="hibernate.c3p0.max_size">${hibernate.c3p0.max_size}</prop>
                <prop key="hibernate.c3p0.timeout">${hibernate.c3p0.timeout}</prop>
                <prop key="hibernate.c3p0.max_statements">${hibernate.c3p0.max_statements}</prop>
                <prop key="hibernate.c3p0.idle_test_period">${hibernate.c3p0.idle_test_period}</prop>
            </props>
        </property>
    </bean>

    <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

</beans>

Класс DAO

ActivityDAO
-----------
package com.adwitiya.vdb.data.activity;

import com.adwitiya.vdb.domain.Activity;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository("activityDAO")
public class ActivityDAO
{
    @Autowired
    private SessionFactory sessionFactory;
    private Session session;
    private boolean status;
    private static Logger logger = Logger.getLogger(ActivityDAO.class);

    public ActivityDAO()
    {
    try
    {
        session = sessionFactory.getCurrentSession();
    }catch(Exception exception)
    {
        logger.error(("Unable to initiate session because of the problem " + exception.getMessage()));
    }
    }

    public boolean add(Activity activity)
    {
    try
    {
        logger.info("Trying to add an activity " + activity.toString());
        session.save(activity);
        status = true;
        logger.info("Added the activity " + activity.toString() + " successfully");
    }catch(HibernateException exception)
    {
        logger.error("Couldn't add an activity " + activity.toString() + " because of the problem " + exception.getMessage());
    }catch(Exception exception)
    {
        logger.error("Couldn't add an activity " + activity.toString() + " because of the problem " + exception.getMessage());
    }
    return status;
    }

    public boolean modify(Activity activity)
    {
    try
    {
        logger.info("Trying to modify the activity " + activity.toString());
        session.saveOrUpdate(activity);
        status = true;
        logger.info("Updated the activity " + activity.toString() + "successfully");
    }catch(HibernateException exception)
    {
        logger.error("Couldn't modify the activity " + activity.toString() + " because of the problem " + exception.getMessage());
    }catch(Exception exception)
    {
        logger.error("Couldn't modify the activity " + activity.toString() + " because of the problem " + exception.getMessage());
    }
    return status;
    }

    public boolean delete(Activity activity)
    {
    try
    {
        logger.info("Trying to delete the activity " + activity.toString());
        session.delete(activity);
        status=true;
        logger.info("Deleted the activity " + activity.toString() + " successfully");
    }catch(HibernateException exception)
    {
        logger.error("Couldn't delete the activity " + activity.toString() + " because of the problem " + exception.getMessage());
    }catch(Exception exception)
    {
        logger.error("Couldn't delete the activity " + activity.toString() + " because of the problem " + exception.getMessage());
    }
    return status;
    }

    public SessionFactory getSessionFactory()
    {
    return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory)
    {
    this.sessionFactory = sessionFactory;
    }

    public Session getSession()
    {
    return session;
    }

    public void setSession(Session session)
    {
    this.session = session;
    }

    public boolean isStatus()
    {
    return status;
    }

    public void setStatus(boolean status)
    {
    this.status = status;
    }
}

И, наконец, класс ActivityDAOTest

ActivityDAOTest
---------------

package com.adwitiya.vdb.data.activity;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration( locations = { "classpath:vdb-servlet.xml", "classpath:vdb-data.xml"})
public class ActivityDAOTest
{
    public ActivityDAOTest()
    {
    }

    @Test
    public void testConstructor()
    {
    Session thisSession = new Configuration().configure().buildSessionFactory().openSession();
    ApplicationContext appcontext = new AnnotationConfigApplicationContext("com.adwitiya.vdb");
    ActivityDAO activityDAO = (ActivityDAO) appcontext.getBean("ActivityDAO");
    Session session = activityDAO.getSession();
    assertEquals(thisSession,session);
    }
}

person Vishwas Shashidhar    schedule 19.12.2012    source источник
comment
Я хотел бы заявить, что то, что вы делаете, - это скорее интеграционное тестирование, а не модульное тестирование. Когда мы модульно тестируем бины Spring, мы тестируем их изолированно, то есть без контейнера, и предоставляем зависимости вручную.   -  person Boris Treukhov    schedule 20.12.2012
comment
Хорошо .. Не могли бы вы посоветовать, как мне поступить в этом случае?   -  person Vishwas Shashidhar    schedule 20.12.2012
comment
Вместо того, чтобы создавать AnnotationConfigApplicationContext вручную в тесте integration, вы должны использовать структуру Spring Test Context, как предложил Бенуа. Также не понятно, что должен делать thisSession, но это не имеет значения, потому что использование @RunWith(SpringJUnit4ClassRunner.class) в любом случае является очевидным выбором.   -  person Boris Treukhov    schedule 20.12.2012
comment
Хорошо спасибо. Я пройдусь по некоторым материалам и попытаюсь найти способ.   -  person Vishwas Shashidhar    schedule 20.12.2012


Ответы (1)


Вам нужно настроить JUnit так, чтобы он поддерживал инъекцию Spring, используя аннотацию:

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)

Затем вы можете автоматически подключить свой DAO, чтобы проверить его работу:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( locations = { "classpath:vdb-servlet.xml", "classpath:vdb-data.xml"})
public class ActivityDAOTest
{
    @Autowired
    private ActivityDAO activityDAO;

    @Test
    public void testConstructor(){
        activityDAO.methodTotest();
    }
}
person Benoit Wickramarachi    schedule 19.12.2012
comment
Спасибо, чувак ... кажется, это помогает ... но бегаешь с еще несколькими ошибками :) Постараюсь решить одну проблему за раз ... - person Vishwas Shashidhar; 20.12.2012