2014-10-07 37 views
5

entegrasyon testinde talep edildiğinde veri içe aktarılamaz veya mevcut olmayabilir Eğer aşağıdaki kurulumla dbunit çalıştırırsam ve bir entegrasyon testinde HTTP üzerinden veri talep edersem veri tabanım olmadığı için veri alamadım boş. DBUnit, verileri veritabanına yazar, ancak verileri HTTP üzerinden istediğimde boştur. yay çizme-marş-web (dışlamak erkek kedi), yay çizme-marş-iskelesi, yay çizme-marş-veri-JPA, bahar-BOOT- ile Bahar Boot 1.1.7: DBUnit ve Spring Boot - Bir tümleştirme sınamasında

Bu

benim kurulduğundan Başlangıç ​​testi, liquibase çekirdekli, DBUnit 2.5.0 yay test DBUnit 1.1.0

Esas uygulama sınıfı:

@Configuration 
@ComponentScan 
@EnableAutoConfiguration 
@RestController 
@EnableTransactionManagement 
@EnableJpaRepositories 

test konfigürasyonu (uygulama test.yaml):

logging.level.org.springframework: DEBUG 
logging.level.org.dbunit: DEBUG 

spring.jpa.properties.hibernate.hbm2ddl.auto: update 
spring.jpa.database: h2 
spring.jpa.show-sql: true 

// setting these properties to access the database via h2 console 
spring.datasource.url: jdbc:h2:tcp://localhost/mem:my_db;DB_CLOSE_DELAY=-1;MVCC=true;DB_CLOSE_ON_EXIT=FALSE 
spring.datasource.username: sa 
spring.datasource.password: sa 
spring.datasource.driverClassName: org.h2.Driver 
spring.jpa.database-platform: org.hibernate.dialect.H2Dialect 

liquibase.change-log: classpath:/db/changelog/db-master.xml 

Integ rasyon testi:

@ActiveProfiles("test") 
@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = HDImageService.class) 
@TestExecutionListeners({ 
    DependencyInjectionTestExecutionListener.class, 
    DbUnitTestExecutionListener.class }) 
@WebAppConfiguration 
@IntegrationTest("server.port:0") 
@DatabaseSetup("/database_seed.xml") 
@DatabaseTearDown(value = "/database_tear_down.xml", type = DatabaseOperation.DELETE_ALL) 

// test 
@Test 
public void get_works() throws Exception { 
    // given 
    String url = host + port + "/my-resource/1"; 

    // when 
    ResponseEntity<String> response = template.getForEntity(url, String.class); 

    // then 
    assertThat(response.getStatusCode(), is(HttpStatus.OK)); 
} 

Ben zaten veritabanına enjekte deposu üzerinden testinde yazma çünkü, kişiler, depo, denetleyici, ... ama bu bileşenlerin gibi burada başka çalışıyoruz hepsini yüklemek ve alabilir HTTP üzerinden. Yani sorun dbunit üzerinden ithalat, çalışma değil ... Daha önce bir eski projeksiyonda, ancak önyükleme ile birlikte dbunit başarıyla kullandım. Belki de icra dinleyicileri bahar botlarıyla benzer değiller mi?

Hata ayıklama dbunit sınıflarını attı ve tüm hata ayıklama günlüğü çıktılarını okudum, ancak anlamadım. DBUnit, önyükleme oluşturulmuş dataSource (yukarıda yapılandırılmış) kullanıyor, bu yüzden aynı veritabanı.

entegrasyon testleri başlatırken, aşağıdaki gerçekleşmesi geçerli:
- liquibase liquibase yapılandırmasına göre veritabanı şemasını oluşturur
- veritabanına eklemek DbUnit (log diyor (zaten daha önce şema itti belki JPA?)

bir alt Arıyorum: - çıkış ve hata ayıklama)
404 Get girilmez

Güncelleme) Belirtilen kimliğe sahip veritabanında bulunduğunda ben 404 dönmek (bulunamadı dbunit için ernative, ama iyi bir çözüm bulamıyor. Peki, bütünleştirme testleriniz için veritabanınızı nasıl hazırlıyorsunuz? Aslında verilere beklenildiği gibi devam ederse, her testten önce veya testten önce bireylerin verilerini içe aktarmaya ihtiyacım var.

Güncelleme. Standart değerlerle ben tam spring.datasource kaldırıldı

DB_CLOSE_DELAY=-1;MVCC=true;DB_CLOSE_ON_EXIT=FALSE 

* yapılandırma yayı yaratıyor veri kaynağı: Ben h2 veritabanına bağlanmak için aşağıdaki seçenekleri kullanın

ve bir bellek içi h2 veritabanı sunucusunu başlat. Bu dbunit hala veritabanı tablosu kilitler ve test içinde gönderilen HTTP isteği, veritabanı tablonun erişimi yoktur çünkü ben bahsettiğim seçenekler ve org.hibernate.PessimisticLockException olsun, yapılacaktır. Bunun nedeni, daha yüksek eşzamanlılık ekleyen MVCC=true; seçeneğidir, temel olarak sorun nedir, neden hiçbir veri yoktur: "Yalnızca bağlantılar", "taahhüt edilen veriye ve kendi değişikliklerine" bakın. Veritabanına HTTP isteği üzerinden erişilirken, dbunit verileri mevcut değil, çünkü dbunit verileri yay bağlantısı için işlenmemiş ...

Peki, h2 (ve ayrıca derbi) veritabanı tablolarının neden dbunit tarafından kilitlendiğini bilen var mı?

cevap

5

Sonunda bu sorun için bir çözüm buldum.

İşaret ettiğim PessimisticLockException ile doğru yöndeydi. DBUnit veritabanı bağlantısını yayınlamadı, bu nedenle yay bağlantısı, kilitli olduğu veritabanı tablosuna erişemedi.

Kendi veritabanı işlemimi gerçekleştirdim. customize DBUnit database options seçeneğini kullandım. Her şeyden

Önce Ben çeki jdbcConnection.getAutoCommit() == false kaldırıldı ve oto yanlış taahhüt otomatik ayarlamadan önce değerini taahhüt kaydedilmiş farkla, DBUnit ait TransactionOperation dayalı AutoCommitTransactionOperation denilen bir sınıf uyguladı.

public class AutoCommitTransactionOperation extends DatabaseOperation { 

    private final DatabaseOperation _operation; 

    public AutoCommitTransactionOperation(DatabaseOperation operation) { 
     _operation = operation; 
    } 

    public static final DatabaseOperation AUTO_COMMIT_TRANSACTION(DatabaseOperation operation) { 
     return new AutoCommitTransactionOperation(operation); 
    } 

    public void execute(IDatabaseConnection connection, IDataSet dataSet) throws DatabaseUnitException, SQLException { 
     logger.debug("execute(connection={}, dataSet={}) - start", connection, dataSet); 

     IDatabaseConnection databaseConnection = connection; 
     Connection jdbcConnection = databaseConnection.getConnection(); 

     boolean autoCommit = jdbcConnection.getAutoCommit(); 
     jdbcConnection.setAutoCommit(false); 
     try { 
      _operation.execute(databaseConnection, dataSet); 
      jdbcConnection.commit(); 
     } catch (DatabaseUnitException e) { 
      jdbcConnection.rollback(); 
      throw e; 
     } catch (SQLException e) { 
      jdbcConnection.rollback(); 
      throw e; 
     } catch (RuntimeException e) { 
      jdbcConnection.rollback(); 
      throw e; 
     } finally { 
      jdbcConnection.setAutoCommit(autoCommit); 
     } 
    } 
} 

Sonra DatabaseLookup oluşturuldu: taahhüt sonra eskisi gibi aynı duruma sahip üzere, geri kaydedilen değere değerini ayarlayın. ... Bu daha kesmek olmadığından emin değilim

@DbUnitConfiguration(databaseOperationLookup = AutoCommitTransactionDatabaseLookup.class) 

benim kesmek için herhangi bir ipucu:

public class AutoCommitTransactionDatabaseLookup extends DefaultDatabaseOperationLookup { 

    @Override 
    public org.dbunit.operation.DatabaseOperation get(DatabaseOperation operation) { 
     if (operation == operation.CLEAN_INSERT) { 
      return AutoCommitTransactionOperation.AUTO_COMMIT_TRANSACTION(org.dbunit.operation.DatabaseOperation.CLEAN_INSERT); 
     } 
     return super.get(operation); 
    } 
} 

ve benim test sınıfa eklendi?

+0

Çözünürlüğünüzü bu kadar ayrıntıda paylaştığınızı kesinlikle harika buluyorum. Evde kendi kukla projemde, çözümünüzle ve çözümünüz olmadan çalışsam da, işte aynı problemle karşılaştığımı düşünüyorum. Pazartesi günü işte çalışacağım, bu kesin. –

+0

Teşekkürler! Sende de aynı problem mi var? – David