2013-07-12 4 views
6

ProductDAO 클래스의 JUnit 테스트 케이스를 실행하려고합니다. 이는 스프링 웹 애플리케이션의 일부입니다. 그러나 여전히 실패합니다. 내 test-context.xml 파일로 확신 할 수 없다.Spring JUnit 테스트 케이스가 실패했습니다

경로 src/test/javaProductDAOImplTest 클래스가 있고 스택 트레이스의 ProductController 클래스가 경로 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> 

스택 트레이스

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

당신의'file : src/test/resources/test-context.xml'은'çlasspath : test-context.xml'로 사용 가능해야한다고 생각합니다. –

답변

7

주석 수 단위 테스트보다 더 많은 통합 테스트.

내 주요 제안은 테스트중인 구성 요소에 절대적으로 필요한 시스템의 일부만 가져 오는 것입니다. ProductDAO.

이미 어느 정도이 일을하는 것 또한 도움이 당신의 예의 DAO, 유지 곳으로 component-scan의 범위를 감소되어 있습니다 무엇 :

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

을이 따기가 높을 피할 것 컨트롤러 및 서비스와 같은 고급 구성 요소.

그런 다음 컨텍스트의 이름을 test-dao-context.xml으로 바꿔 다른 모든 DAO 테스트에서 사용할 수 있습니다.

서비스를 통합 테스트 할 때 컨텍스트를 가져 와서 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]

문제는 간단한 봄 테스트는 봄 웹 응용 프로그램 컨텍스트 기능없이, 베어 봄 apprlication 문맥으로 실행한다는 것입니다. 따라서이 경우 HttpServletRequests, Servlet Context 및 기타 기능을 사용할 수 없습니다.

@WebAppConfiguration 주석을 테스트 클래스에 추가해보십시오.

이 옵션은 Spring 3.2 이상 버전에서만 사용할 수 있습니다.

이전 버전의 Spring에서는 응용 프로그램 컨텍스트에서이 인터페이스 구현을 사용 가능하게 만들기 위해 무언가를 고안해야합니다. 가장 간단한 것은 MockServletContext 클래스 및/또는 HttpServletRequest 인터페이스를 테스트 용 Bean으로 노출하는 것입니다.

또한 세션 범위 bean을 사용하는 코드는 컨트롤러마다 다르며 web application context에 속하므로 @WebAppConfiguration이라는 별도의 테스트를 통해 컨트롤러를 테스트하는 것이 가장 좋습니다. 오래된 응용 프로그램 컨텍스트에서 루트 응용 프로그램 컨텍스트에 속하는 오래된 빈과 서비스 (예 : @WebAppConfiguration 제외).

ProductDAO은 루트 응용 프로그램 컨텍스트에 속하며 ProductController은 웹 응용 프로그램 컨텍스트에 속해 있으므로 해당 정의가 다른 xml 파일에 있어야합니다.ProductDAO 테스트는 루트 앱 컨텍스트 전용의 xml을 가리켜 야하며 @WebAppConfiguration을 포함해야합니다. 내가이 말을하지만

루트 애플리케이션 컨텍스트 및 웹 응용 프로그램 컨텍스트 XML 파일 (예제 How to Setup web application context in Spring MVC test 참조) 모두를 가리켜 야한다 ProductController 시험으로

와는 당신이 현재하고있는 것은 괜찮 @WebAppConfiguration

+1

감사합니다. Boris .. 내 하루를 저장했습니다 :) – stinepike

0

나는 gerrytan과 Jonathan이 쓴 내용에 동의합니다. 나는 또한 조롱을 쉽게하기 위해 Springockito을 살펴볼 것을 제안합니다.

관련 문제