2013-07-12 7 views
6

Я пытаюсь запустить тестовый пример JUnit для класса ProductDAO, который является частью весеннего веб-приложения. Но он все еще терпит неудачу. Я не уверен в моем файле test-context.xml.Ошибка теста Spring JUnit

У меня есть ProductDAOImplTest класса по пути src/test/java и упомянутый ProductController класса в StackTrace сохраняются в пути src/main/java.

ProductDAOImplTest

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("file:src/test/resources/test-context.xml") 
@Transactional 
public class ProductDAOImplTest { 

    @Autowired 
    private ProductDAO productDAO; 

    @Test 
    public void testAdd() { 
     fail("Not yet implemented"); 
    } 

    @Test 
    public void testEdit() { 
     fail("Not yet implemented"); 
    } 

    @Test 
    public void testGetAll() { 
     fail("Not yet implemented"); 
    } 

    @Test 
    public void testGet() { 
     fail("Not yet implemented"); 
    } 

    @Test 
    public void testRemove() { 
     fail("Not yet implemented"); 
    } 

    @Test 
    public void testGetByPage() { 
     fail("Not yet implemented"); 
    } 

} 

тест-context.xml

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

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

    <!-- JDBC --> 
    <bean id="propertyConfigurer" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" 
     p:location="file:src/main/webapp/WEB-INF/jdbc.properties" /> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
     destroy-method="close" p:driverClassName="${jdbc.driverClassName}" 
     p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> 

    <!-- Hibernate --> 
    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="configLocation"> 
      <value>classpath:hibernate.cfg.xml</value> 
     </property> 
     <property name="configurationClass"> 
      <value>org.hibernate.cfg.AnnotationConfiguration</value> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">${jdbc.dialect}</prop> 
       <prop key="hibernate.show_sql">true</prop> 
      </props> 
     </property> 
    </bean> 

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



</beans> 

StackTrace

java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157) 
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:103) 
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:73) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:313) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.servlet.http.HttpServletRequest com.myapp.controller.ProductController.request; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.servlet.http.HttpServletRequest] 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) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1120) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:106) 
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:57) 
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100) 
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248) 
    at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) 
    ... 24 more 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.servlet.http.HttpServletRequest com.myapp.controller.ProductController.request; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.servlet.http.HttpServletRequest] 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:514) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285) 
    ... 40 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [javax.servlet.http.HttpServletRequest] 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:949) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:818) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:730) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) 
    ... 42 more 
+0

Я думаю, что ваш 'файл: src/test/resources/test-context.xml' должен быть доступен как' çlasspath: test-context.xml' –

ответ

7

Что вы делаете в настоящее время в порядке, хотя я бы сказал, больше теста интеграции, чем единичный тест.

Мое основное предположение заключалось бы в том, чтобы приводить в действие только части системы, которые вам абсолютно необходимы для тестируемого компонента, например. ProductDAO.

Вы уже, кажется, делают это в определенной степени, но то, что может помочь в снижении масштабов вашего component-scan, где вы храните свои объекты DAO, например:

<context:component-scan base-package="com.myapp.dao" /> 

Это позволило бы избежать собирание более высокого таких как контроллеры и службы.

Затем вы можете переименовать контекст в test-dao-context.xml и использовать его во всех своих других тестах DAO.

Когда вы приходите на интеграцию, проверяя свои Службы, тогда у вас может быть контекст test-service-context.xml, который импортирует test-dao-context.xml, что позволяет вам тестировать из службы в базу данных без чрезмерного повторения определений bean-компонентов.

+0

Спасибо, изменение пакета для проверки компонентов разрешило проблему. Является ли предложенный способ стандартным весенним каркасом или трюком? – misco

+1

@misco Я не могу сказать, стандартно ли это, но для меня это хорошо работает. Я рад, что вы решили свою проблему. – Jonathan

4

Ваш блок тест установки сделать меня (очень) нервной. Вы пытаетесь загружать все, включая спящий режим, диспетчер транзакций и сканирование компонентов. Для этого вам почти нужен свой собственный контейнер.

Обычно хороший тест блок фокусируется на одном классе только в тестовом классе, все его зависимости издевались с использованием библиотек, таких как Mockito

+0

Я начинаю тестировать весну, так как должен выглядеть правильный модульный тест настроить? – misco

+2

Тестирование в вопросе не является единичным тестом, но в этом нет ничего плохого - это интеграционный тест в контейнере, который тестирует конфигурацию контекста Spring и компоненты (JUnit - это просто инструмент для запуска теста в этом случае) , –

21

Ошибка в трассировки стека

Не удалось autowire поле: частный javax.servlet.http.HttpServletRequest com.myapp.controller.ProductController.request; ... Нет соответствие рожкового типа [javax.servlet.http.HttpServletRequest]

Проблема заключается в том, что простые тестах Spring работать с голым контекстом Spring apprlication, без возможности контекста Spring Web Application. Таким образом, HttpServletRequests, контекст сервлета и другие функции недоступны в этом случае.

Попробуйте добавить @WebAppConfiguration аннотация к тестовому классу.

Обратите внимание, что эта опция доступна только в версиях Spring 3.2+.

В старых версиях Spring вам нужно придумать что-то, чтобы реализовать реализационные реализации этого интерфейса в контексте приложения (наиболее простой задачей является выявление класса MockServletContext и/или интерфейса HttpServletRequest в качестве компонентов для тестов).

Также обратите внимание, что код, использующий бозонные области сеанса, обычно является специфичным для контроллера и относится к web application context, и я считаю, что будет лучше всего тестировать контроллеры в отдельных тестах с помощью @WebAppConfiguration, но оставить тесты равнины старые бобы и службы, относящиеся к корневому контексту приложения в простых контекстах приложения, то есть без @WebAppConfiguration.

Только для того, чтобы быть ясным ProductDAO относится к корневому контексту приложения, а ProductController относится к контексту веб-приложения, поэтому их определения должны размещаться в разных файлах xml.ProductDAO тест должен указывать на xml только контекстного контекста приложения и не содержать @WebAppConfiguration.

Что касается ProductController теста необходимо указать как для корневого контекста приложения и веб-контекст приложения файлы XML (см How to Setup web application context in Spring MVC test для примера) и быть с аннотацией @WebAppConfiguration

+1

спасибо Борису .. вы спасли мой день :) – stinepike

0

Я согласен с тем, что написал Джерритан и Джонатан. Я бы также предложил взглянуть на Springockito для более простого издевательств.

Смежные вопросы