2013-07-12 30 views
6

Tôi cố gắng chạy một trường hợp kiểm tra JUnit cho lớp ProductDAO, đó là một phần của ứng dụng web mùa xuân. Nhưng nó vẫn thất bại. Tôi không chắc chắn bởi tập tin test-context.xml của tôi.Trường hợp thử nghiệm Spring JUnit không thành công

Tôi có ProductDAOImplTest lớp trong đường dẫn src/test/java và được đề cập ProductController lớp trong ngăn xếp được lưu trong đường dẫn 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"); 
    } 

} 

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

Tôi nghĩ tệp 'src/test/resources/test-context.xml' của bạn nên có sẵn dưới dạng' çlasspath: test-context.xml' –

Trả lời

7

gì bạn đang làm là tốt, mặc dù tôi sẽ nói đó là nhiều thử nghiệm tích hợp hơn thử nghiệm đơn vị.

Đề xuất chính của tôi là chỉ đưa các phần của hệ thống mà bạn hoàn toàn cần cho thành phần đang thử nghiệm, ví dụ: số ProductDAO.

Bạn đã dường như được làm điều này đến một mức độ nhất định nhưng những gì cũng có thể giúp đỡ được giảm phạm vi component-scan của bạn đến nơi mà bạn giữ DAO của bạn, ví dụ:

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

Điều này sẽ tránh nhặt higher- các thành phần mức độ như Bộ điều khiển và Dịch vụ.

Sau đó, bạn có thể đổi tên ngữ cảnh thành test-dao-context.xml và sử dụng nó trong tất cả các bài kiểm tra DAO khác của bạn.

Khi bạn đi thử nghiệm tích hợp Dịch vụ, bạn có thể có ngữ cảnh test-service-context.xml nhập test-dao-context.xml cho phép bạn kiểm tra từ dịch vụ tới cơ sở dữ liệu mà không lặp lại quá nhiều định nghĩa bean.

+0

Cảm ơn, sự thay đổi của gói cho quét thành phần đã giải quyết được vấn đề. Là cách đề xuất một tiêu chuẩn của khung mùa xuân hoặc lừa của bạn? – misco

+1

@misco Tôi không thể nói nếu đó là tiêu chuẩn, nhưng nó đã làm việc tốt cho tôi cho đến nay. Tôi rất vui vì bạn đã giải quyết được sự cố của mình. – Jonathan

4

của bạn thiết lập kiểm tra đơn vị làm cho tôi (rất) lo lắng. Bạn đang cố gắng khởi động mọi thứ bao gồm ngủ đông, quản lý giao dịch và quét thành phần. Bạn gần như cần container riêng của bạn để làm điều này.

Điển hình là một thử nghiệm đơn vị tốt tập trung vào một lớp chỉ mỗi lớp thử nghiệm, tất cả phụ thuộc của nó đang chế giễu sử dụng thư viện như Mockito

+0

Tôi là người mới bắt đầu trong thử nghiệm vào mùa xuân, vì vậy, hãy xem bài kiểm tra đơn vị chính xác như thế nào thiết lập? – misco

+2

Bài kiểm tra trong câu hỏi không phải là bài kiểm tra đơn vị, nhưng không có gì sai với nó - đó là kiểm thử tích hợp trong thùng chứa để kiểm tra cấu hình ngữ cảnh mùa xuân và các hạt (JUnit là một công cụ để chạy thử nghiệm trong trường hợp này) . –

21

Lỗi này là trong stack trace

Không thể autowire lĩnh vực: riêng javax.servlet.http.HttpServletRequest com.myapp.controller.ProductController.request; ... Không phù hợp đậu các loại [javax.servlet.http.HttpServletRequest]

Vấn đề là xét nghiệm đơn giản mùa xuân chạy với bối cảnh mùa xuân apprlication để trần, không khả năng bối cảnh mùa xuân ứng dụng Web. Vì vậy, HttpServletRequests, Servlet Context và các tính năng khác không có sẵn trong trường hợp này.

Thử thêm @WebAppConfiguration chú thích vào lớp kiểm tra.

Xin lưu ý rằng tùy chọn này chỉ có sẵn trong phiên bản Spring 3.2+.

Trong các phiên bản cũ của Spring, bạn sẽ cần phát minh ra thứ gì đó để làm cho việc triển khai giao diện này có sẵn trong ngữ cảnh ứng dụng (điều đơn giản nhất là hiển thị giao diện của lớp MockServletContext và/hoặc HttpServletRequest). Cũng xin lưu ý rằng mã sử dụng đậu phạm vi phiên thường là bộ điều khiển cụ thể và thuộc về web application context và tôi tin rằng đó sẽ là phương pháp tốt nhất để kiểm tra bộ điều khiển trong các thử nghiệm riêng biệt với @WebAppConfiguration, nhưng để lại các thử nghiệm của đồng bằng đậu cũ và dịch vụ thuộc ngữ cảnh ứng dụng gốc trong ngữ cảnh ứng dụng đơn giản, tức là không có @WebAppConfiguration.

Chỉ cần rõ ràng ProductDAO thuộc về ngữ cảnh ứng dụng gốc và ProductController thuộc ngữ cảnh ứng dụng web, do đó định nghĩa của chúng phải được đặt trong các tệp xml khác nhau.ProductDAO kiểm tra phải trỏ đến xml của ngữ cảnh ứng dụng gốc gốc chỉ và không chứa @WebAppConfiguration.

Đối với ProductController kiểm tra phải trỏ đến cả bối cảnh ứng dụng gốc và bối cảnh ứng dụng web file xml (xem How to Setup web application context in Spring MVC test cho ví dụ) và được chú thích với @WebAppConfiguration

+1

nhờ Boris .. bạn đã lưu ngày của tôi :) – stinepike

0

Tôi đồng ý với những gì gerrytan và Jonathan đã viết. Tôi cũng khuyên bạn nên xem Springockito để chế nhạo dễ dàng hơn.

Các vấn đề liên quan