2011-01-17 37 views
6

Trong các thử nghiệm đơn vị của tôi, tôi autowired một số DataSource, mà sử dụng các URL nhưJUnit + Derby + Mùa xuân: thả trong bộ nhớ db sau mỗi lần kiểm tra

jdbc:derby:memory:mydb;create=true 

để tạo ra một trong bộ nhớ DBS.

Để thả một Derby trong bộ nhớ db bạn phải kết nối với:

jdbc:derby:memory:mydb;drop=true 

Tôi muốn điều này xảy ra sau mỗi lần thử nghiệm và bắt đầu với một db tươi. Làm thế nào tôi có thể làm điều này bằng cách sử dụng Spring?

Trả lời

4

How to shutdown Derby in-memory database Properly

đã cho tôi một gợi ý đến một giải pháp:

mydb.drop.url = jdbc:derby:memory:mydb;drop=true 

    ... 

    <bean id="mydbDropUrl" class="java.lang.String"> 
    <constructor-arg value="${mydb.drop.url}" /> 
</bean> 

    ... 

    @Resource 
private String mydbDropUrl;   

    @After 
public void tearDown() { 
    try { 
     DriverManager.getConnection(mydbDropUrl); 
    } catch (SQLException e) { 
     // ignore 
    } 
} 

Một nhược điểm là việc sử dụng các constructor String mà chấp nhận một String (một đối tượng String bất biến xung quanh một đối tượng String không thay đổi). Tôi đọc rằng có một chú thích @Value trong Spring 3, có thể trợ giúp ở đây, nhưng tôi đang sử dụng Spring 2.5.

Vui lòng cho tôi biết nếu bạn có giải pháp đẹp hơn.

+0

Theo http://docs.oracle.com/javadb/10.8.1.2/getstart/rwwdactivity3.html làm ví dụ, thay vì chỉ đơn giản là bắt và loại bỏ 'SQLException', có thể tốt hơn nếu loại bỏ nó chỉ khi' e.getSQLState() .equals ("08006") ' – Raedwald

1

Nếu bạn sử dụng thư việnmùa xuân-test.jar, bạn có thể làm một cái gì đó như thế này:

public class MyDataSourceSpringTest extends 
AbstractTransactionalDataSourceSpringContextTests { 

    @Override 
    protected String[] getConfigLocations() { 
     return new String[]{"classpath:test-context.xml"}; 
    } 

    @Override 
    protected void onSetUpInTransaction() throws Exception { 
     super.deleteFromTables(new String[]{"myTable"}); 
     super.executeSqlScript("file:db/load_data.sql", true); 
    } 
} 

Và một phiên bản cập nhật dựa trên bình luận mới nhất, mà giọt db và tái tạo lại bảng trước mỗi bài kiểm tra:

public class MyDataSourceSpringTest extends 
    AbstractTransactionalDataSourceSpringContextTests { 

     @Override 
     protected String[] getConfigLocations() { 
      return new String[]{"classpath:test-context.xml"}; 
     } 

     @Override 
     protected void onSetUpInTransaction() throws Exception { 
      super.executeSqlScript("file:db/recreate_tables.sql", true); 
     } 
} 
+0

yup, biết libs của bạn (+1) –

+0

Tôi không muốn xóa dữ liệu khỏi bảng hoặc thậm chí là thả bảng. Tôi muốn thả toàn bộ db một tái tạo nó cho mọi thử nghiệm, đó là IMHO an toàn hơn. – Puce

+0

Bạn có thể tạo tập lệnh sql để xóa db và tạo lại các bảng và thực thi nó như được hiển thị ở trên. Tôi sẽ cập nhật câu trả lời của tôi một cách thích hợp. –

1

Chỉ cần làm một cái gì đó như:

public class DatabaseTest implements ApplicationContextAware { 
    private ApplicationContext context; 
    private DataSource source; 

    public void setApplicationContext(ApplicationContext applicationContext) { 
     this.context = applicationContext; 
    } 

    @Before 
    public void before() { 
     source = (DataSource) dataSource.getBean("dataSource", DataSource.class); 
    } 

    @After 
    public void after() { 
     source = null; 
    } 
} 

Làm cho hạt của bạn có phạm vi nguyên mẫu (scope="prototype"). Điều này sẽ nhận được một thể hiện mới của nguồn dữ liệu trước mỗi thử nghiệm.

+0

Đó là thông minh (+1), nhưng không thực tế (có nghĩa là bạn phải tự buộc tất cả các hạt sử dụng nguồn dữ liệu) –

+0

Tôi có nghi ngờ, nếu phương pháp này thực sự hoạt động: Bạn có nói rằng context.getBean() sẽ trả về một cá thể mới thay vì cùng một cá thể? Tôi không nghĩ rằng đây là trường hợp, có nghĩa là bạn sẽ không đạt được gì. Có một chú thích @DirtiesContext, nhưng ngay cả điều đó sẽ không mở một kết nối với "jdbc: derby: memory: mydb; drop = true" để xóa db trong bộ nhớ. – Puce

2

Sau khi kiểm tra lò xo 3, bạn có thể sử dụng chú thích để tiêm cấu hình:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/spring-test.xml") 
public class MyTest { 
} 
5

Có một cách cơ sở dữ liệu-agnostic để làm điều này nếu bạn đang sử dụng Spring cùng với Hibernate.

Hãy chắc chắn rằng bối cảnh ứng dụng sẽ được tạo ra/bị phá hủy trước/sau mỗi phương pháp thử nghiệm:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath*:application-context-test.xml"}) 
@TestExecutionListeners({DirtiesContextTestExecutionListener.class, 
    DependencyInjectionTestExecutionListener.class}) 
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 
public abstract class AbstractTest { 

} 

Hướng dẫn, Hibernate để tự động tạo ra các sơ đồ khởi động và để thả các schema trên shutdown:

hibernate.hbm2ddl.auto = create-drop 

Bây giờ trước mỗi thử nghiệm

  • ngữ cảnh ứng dụng được tạo và yêu cầu d đậu xuân được tiêm (mùa xuân)
  • cấu trúc cơ sở dữ liệu được tạo (hibernate)
  • việc nhập.sql được thực hiện nếu có (ngủ đông)

và sau mỗi lần kiểm tra

  • bối cảnh ứng dụng bị phá hủy (mùa xuân)
  • database schema được giảm (hibernate).

Nếu bạn đang sử dụng giao dịch, bạn có thể muốn thêm TransactionalTestExecutionListener.

0

Đây là những gì chúng tôi thực hiện khi bắt đầu mọi thử nghiệm.

  1. Thả tất cả các đối tượng trước đó.

  2. Tạo tất cả các bảng được đề cập trong create_table.sql

  3. Chèn giá trị vào bảng được tạo ra dựa trên những gì bạn muốn kiểm tra.

    @Before 
        public void initialInMemoryDatabase() throws IOException, FileNotFoundException { 
    
        inMemoryDerbyDatabase.dropAllObjects(); 
        inMemoryDerbyDatabase.executeSqlFile("/create_table_policy_version_manager.sql"); 
        inMemoryDerbyDatabase.executeSqlFile("/insert_table_policy_version_manager.sql"); 
    
        } 
    

trình như một say mê!

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