2011-12-21 28 views
6

Tôi đang gặp sự cố khi cố gắng đẩy các thay đổi được thực hiện trong giao dịch Hibernate đến cơ sở dữ liệu để DbUnit hoạt động đúng trong trường hợp thử nghiệm của tôi. Dường như DbUnit không nhìn thấy những thay đổi được thực hiện bởi Hibernate bởi vì họ không cam kết vào cuối của giao dịch được nêu ra ... và tôi không chắc chắn làm thế nào để cơ cấu lại trường hợp thử nghiệm của tôi để có được điều này để làm việc.Bắt DbUnit để làm việc với giao dịch Hibernate

Đây là trường hợp thử nghiệm quá đơn giản của tôi để chứng minh vấn đề của tôi: -

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { 
     "classpath:applicationContext-test.xml" 
}) 
@TransactionConfiguration(transactionManager = "transactionManager") 
@Transactional 
public class SomeTest { 
    @Autowired 
    protected DataSource dataSource; 

    @Autowired 
    private SessionFactory sessionFactory; 

    @Test 
    public void testThis() throws Exception { 
     Session session = sessionFactory.getCurrentSession(); 

     assertEquals("initial overlayType count", 4, session.createQuery("from OverlayType").list().size()); 

     //----------- 
     // Imagine this block is an API call, ex: someService.save("AAA"); 
     // But for the sake of simplicity, I do it this way 
     OverlayType overlayType = new OverlayType(); 
     overlayType.setName("AAA"); 
     session.save(overlayType); 
     //----------- 

     // flush has no effect here 
     session.flush(); 

     assertEquals("new overlayType count", 5, session.createQuery("from OverlayType").list().size()); 

     // pull the data from database using dbunit 
     IDatabaseConnection connection = new DatabaseConnection(dataSource.getConnection()); 
     connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory()); 
     QueryDataSet partialDataSet = new QueryDataSet(connection); 
     partialDataSet.addTable("resultSet", "select * from overlayType"); 
     ITable actualTable = partialDataSet.getTable("resultSet"); 

     // FAIL: Actual row count is 4 instead of 5 
     assertEquals("dbunit's overlayType count", 5, actualTable.getRowCount()); 

     DataSourceUtils.releaseConnection(connection.getConnection(), dataSource); 
    } 
} 

toàn bộ ý tưởng của tôi trong việc sử dụng DbUnit là: -

  • Gọi someService.save(...) mà lưu dữ liệu thành nhiều bảng.
  • Sử dụng DbUnit để nhận bảng dự kiến ​​từ XML.
  • Sử dụng DbUnit để nhận bảng thực tế từ cơ sở dữ liệu.
  • Làm Assertion.assertEquals(expectedTable, actualTable);.

Nhưng, tại thời điểm này, tôi không thể nhận được DbUnit để xem các thay đổi được thực hiện bởi Hibernate trong giao dịch.

Tôi nên thay đổi như thế nào để DbUnit hoạt động tốt với giao dịch Hibernate?

Cảm ơn.

Trả lời

9

Tôi chưa bao giờ làm việc với DbUnit, nhưng nó có vẻ như TransactionAwareDataSourceProxy sẽ làm các trick. Về cơ bản bạn cần phải quấn nguồn dữ liệu ban đầu của bạn với proxy này và sử dụng nó thay thế, do đó mã này:

new DatabaseConnection(dataSource.getConnection()) 

thực sự đi qua proxy và sử dụng các giao dịch và kết nối như Hibernate cùng.

Tôi đã tìm thấy Transaction aware datasource (use dbunit & hibernate in spring) bài đăng trên blog giải thích điều này.

Một cách tiếp cận khác là bỏ qua kiểm tra giao dịch hoàn toàn và dọn dẹp cơ sở dữ liệu thay vì theo cách thủ công. Kiểm tra của tôi transactional tests considered harmful artcle.

+0

+1 Câu trả lời hay đấy Tomasz! – Nilesh

0

Có vẻ như trường hợp kiểm tra đó cần hai giao dịch: một để đặt dữ liệu vào cơ sở dữ liệu và một để lấy dữ liệu vào cơ sở dữ liệu.

gì tôi sẽ làm là:

  • Sử dụng một cơ sở dữ liệu bộ nhớ để các dữ liệu được làm sạch khi kiểm tra đơn vị kết thúc.
  • Xóa chú thích giao dịch và sử dụng phương thức beginTransaction và cam kết trực tiếp phiên.

Số đếm overlaytype ban đầu sẽ là 0, và sau phiên giao dịch được lưu, nó phải là 1.

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