2011-01-04 47 views
8

Tôi đang tìm các phương pháp hay nhất để thiết lập thử nghiệm đơn vị và tích hợp bằng Spring.Mùa xuân: kiểm tra đơn vị và tích hợp

Tôi thường sử dụng 3 loại xét nghiệm:

  • "thật" kiểm tra đơn vị (không phụ thuộc)
  • kiểm tra chạy hoặc là "đơn vị" kiểm tra (trong bộ nhớ db, gọi nội hạt, giả đối tượng , ...) hoặc như thử nghiệm hội nhập (db dai dẳng, gọi điện từ xa, ...)
  • kiểm tra chỉ chạy như thử nghiệm hội nhập

Hiện nay tôi chỉ có các bài kiểm tra của categ thứ hai ory, đó là phần khó khăn. tôi thiết lập một lớp học thử nghiệm cơ bản như:

@ContextConfiguration(locations = { "/my_spring_test.xml" }) 
public abstract class AbstractMyTestCase extends AbstractJUnit4SpringContextTests 

Và "đơn vị" kiểm tra như:

public class FooTest extends AbstractMyTestCase 

với các thuộc tính autowired.

Cách tốt nhất để chạy thử nghiệm trong một môi trường thử nghiệm tích hợp khác là gì? Phân lớp thử nghiệm và ghi đè lên ContextConfiguration?

@ContextConfiguration(locations = { "/my_spring_integration_test.xml" }) 
public class FooIntegrationTest extends FooTest 

Công việc này (tôi hiện không thể dễ dàng kiểm tra ở đây)? Vấn đề với phương pháp này là "@ContextConfiguration (locations = {" /my_spring_integration_test.xml "})" được sao chép rất nhiều.

Mọi đề xuất?

Kính trọng, Florian

+0

Bạn có tìm thấy giải pháp phù hợp cho mình không? – FrVaBe

Trả lời

2

Tôi muốn đi với phiên bản này:

ContextConfiguration(locations = { "/my_spring_test.xml" }) 
public abstract class AbstractMyTestCase extends AbstractJUnit4SpringContextTests 

và trong my_spring_test.xml, tôi muốn sử dụng cơ chế PropertyPlaceHolderConfigurer.

Ví dụ cho JPA:

<context:property-placeholder 
    system-properties-mode="OVERRIDE" 
    location="classpath:test.properties" /> 

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="${test.database.driver}" /> 
    <property name="url" value="${test.database.server}" /> 
    <property name="username" value="${test.database.user}" /> 
    <property name="password" value="${test.database.password}" /> 
</bean> 

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="test" /> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="persistenceXmlLocation" 
      value="classpath:META-INF/persistence.xml" /> 
    <property name="jpaVendorAdapter"> 
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
    <property name="showSql" value="false" /> 
    <property name="generateDdl" value="${test.database.update}" /> 
    <property name="database" value="${test.database.databasetype}" /> 
</bean> 
    </property> 
</bean> 

Bây giờ tất cả các bạn cần làm là có các phiên bản khác nhau của test.properties trên con đường lớp cho trong bộ nhớ và kiểm tra tích hợp thực tế (và dĩ nhiên là các lớp học lái xe tương ứng cần hiện tại). Bạn thậm chí có thể đặt thuộc tính hệ thống để ghi đè lên các giá trị thuộc tính.


Nếu bạn muốn chuẩn bị điều này với con quạ, bạn sẽ thấy rằng việc sao chép tệp bằng maven không phải là nhỏ. Bạn sẽ cần một cách để thực thi mã, các lựa chọn tiêu chuẩn là maven-antrun-plugingmaven-maven-plugin.

Dù bằng cách nào: có hai tệp cấu hình, ví dụ: trong src/main/config và thêm hai thực thi plugin, một trong giai đoạn generate-test-resources và một trong giai đoạn pre-integration-test.Dưới đây là phiên bản GMaven:

<plugin> 
    <groupId>org.codehaus.gmaven</groupId> 
    <artifactId>gmaven-plugin</artifactId> 
    <version>1.3</version> 
    <executions> 
     <execution> 
      <phase>pre-integration-test</phase> 
      <goals> 
       <goal>execute</goal> 
      </goals> 
      <configuration> 
      <source> 
      new File(
       pom.build.testOutputDirectory, 
       "test.properties" 
      ).text = new File(
         pom.basedir, 
         "src/main/config/int-test.properties" 
      ).text; 
      </source> 
      </configuration> 
     </execution> 
     <execution> 
      <phase>generate-test-resources</phase> 
      <goals> 
       <goal>execute</goal> 
      </goals> 
      <configuration> 
      <source> 
      new File(
       pom.build.testOutputDirectory, 
       "test.properties" 
      ).text = new File(
         pom.basedir, 
         "src/main/config/memory-test.properties" 
      ).text; 
      </source> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 
+0

Có, tôi đã sử dụng trình giữ chỗ thuộc tính và nghĩ về việc thay thế tệp trên đường dẫn lớp. Cách dễ nhất để làm điều này với Maven là gì? Các dự án riêng biệt/phụ thuộc mà chỉ chứa một tập tin thuộc tính duy nhất và sau đó tinh chỉnh các phụ thuộc bằng cách nào đó phụ thuộc vào pha/profile? – Puce

+0

@Puce đã thêm mã maven –

+0

Cảm ơn, mặc dù tôi không muốn giới thiệu Groovy cho dự án tại thời điểm này. Tôi nghĩ rằng vấn đề là Maven thiếu hỗ trợ kiểm tra tích hợp thích hợp: http://willcode4beer.com/opinion.jsp?set=maven2_integration-test Tôi sẽ kiểm tra xem tôi có thể làm điều đó bằng cách cắm mave-antrun hay thậm chí với Maven Resources Plugin (tài nguyên: copy-resources) – Puce

4

tôi mở rộng GenericXmlContextLoader

public class MyContextLoader extends GenericXmlContextLoader {

và overrote phương pháp

protected String[] generateDefaultLocations(Class<?> clazz)

để thu thập các tên tập tin cấu hình của một thư mục mà tôi có thể xác định bởi một SystemProperty (-Dtest.config =).

Tôi cũng sửa đổi phương pháp follwowing KHÔNG sửa đổi bất kỳ địa điểm

@Override 
protected String[] modifyLocations(Class<?> clazz, String... locations) { 
    return locations; 
} 

tôi sử dụng bộ nạp bối cảnh này như thế này

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(loader = MyContextLoader.class) 
public class Test { .... } 

Chạy thử nghiệm với một SystemProperty chỉ ra nguồn gốc của các tập tin cấu hình cho phép bây giờ bạn sử dụng các cấu hình hoàn toàn khác nhau.

Việc sử dụng SystemProperty tất nhiên chỉ có một chiến lược để xác định vị trí cấu hình. Bạn có thể làm bất cứ điều gì bạn muốn trong generateDefaultLocations().


EDIT:

Giải pháp này cho phép bạn sử dụng hoàn chỉnh cấu hình bối cảnh ứng dụng khác nhau (ví dụ đối với các đối tượng giả) và không chỉ khác nhau tài sản. Bạn không cần một bước xây dựng để triển khai mọi thứ tới vị trí "classpath" của bạn. Việc triển khai thực hiện cụ thể của tôi cũng sử dụng tên người dùng làm mặc định để tìm thư mục cấu hình (src/test/resources/{user}) nếu không có thuộc tính hệ thống (giúp dễ dàng duy trì môi trường thử nghiệm cụ thể cho tất cả các nhà phát triển trong dự án).

Việc sử dụng PropertyPlaceholder ist vẫn có thể và được khuyến nghị.


EDIT:

Xuân Version 3.1.0 sẽ hỗ trợ XML profiles/Environment Abstraction mà là tương tự như giải pháp của tôi và sẽ cho phép lựa chọn các tập tin cấu hình cho các môi trường khác nhau/hồ sơ.

+0

Điều này nghe có vẻ thú vị. Cảm ơn! – Puce

+0

@Puce Hãy xem các tính năng mới trong bản phát hành Mùa xuân 3.1.0 sắp tới (xem EDIT cuối cùng của tôi). – FrVaBe

0

Tôi đã không thành công trong việc sử dụng ngữ cảnh Mùa xuân 3.x: thẻ trình giữ chỗ thuộc tính. Tôi đã sử dụng thẻ đậu thời trang cũ cùng với một tập tin thuộc tính và đã có thể thiết lập một kết nối giữa mã của tôi và cơ sở dữ liệu của tôi như vậy:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="location" value="/com/my/package/database.properties"/> 
</bean> 


<bean id="myDatasource" class="oracle.ucp.jdbc.PoolDataSourceFactory" 
    factory-method="getPoolDataSource"> 
    <property name="URL" value="${JDBC_URL}"/> 
    <property name="user" value="${JDBC_USERNAME}"/> 
    <property name="password" value="${JDBC_PASSWORD}"/> 
    <property name="connectionFactoryClassName" 
     value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/> 
    <property name="ConnectionPoolName" value="SCDB_POOL"/> 
    <property name="MinPoolSize" value="5"/> 
    <property name="MaxPoolSize" value="50"/> 
    <property name="connectionWaitTimeout" value="30"/> 
    <property name="maxStatements" value="100"/> 
</bean> 

Dưới đây là một ví dụ về các thuộc tính file:

JDBC_URL=jdbc:oracle:thin:@myDB:1521:mySchema 
JDBC_USERNAME=username 
JDBC_PASSWORD=password 

Sau đó, tôi thiết lập thử nghiệm JUnit tôi như vậy:

@ContextConfiguration(locations = {"/com/my/pkg/test-system-context.xml"}) 
@RunWith(SpringJUnit4ClassRunner.class) 
public class HeaderDaoTest { 

    @Autowired 
    HeaderDao headerDao; 

    @Test 
    public void validateHeaderId() { 
     int headerId = 0; 

     headerId = headerDao.getHeaderId(); 

     assertNotSame(0,headerId); 
    } 

} 

Đó làm việc cho tôi, nhưng tất cả mọi người làm việc khác một chút. Hi vọng điêu nay co ich.

0

Gần đây, tôi đã gặp phải sự cố tương tự và nhìn vào số documentation for the @ContextConfiguration annotation, tôi nhận thấy tùy chọn inheritLocations.

Bằng cách thêm mục này vào lớp của tôi, ví dụ:

@ContextConfiguration(locations = { "/my_spring_integration_test.xml" }, inheritLocations=false) 
public class FooIntegrationTest extends FooTest 

Tôi thấy rằng tôi có thể ghi đè lên ContextConfiguration như mong muốn.

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