2014-10-07 7 views
5

Se eseguo dbunit con la seguente configurazione e richiedo i dati tramite HTTP in un test di integrazione, non ho ricevuto alcun dato perché il database è vuoto. DBUnit scrive i dati nel database, ma è vuoto quando richiedo i dati via HTTP.DBUnit e Spring Boot - I dati non possono essere importati o esistenti quando si richiede un test di integrazione

Questa è la mia messa a punto: Primavera Boot 1.1.7 con molla-boot-starter-web (escludere Tomcat), la primavera-boot-starter-molo, la primavera-boot-starter-dati-JPA, la primavera-boot avviamento-test, liquibase-core, DBUnit 2.5.0, la primavera-test-DBUnit 1.1.0

applicazione principale Classe:

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

configurazione di prova (application-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 Test razione:

@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)); 
} 

ho potuto postare tutto il resto qui, come entità, repository, controllo, ... ma questi componenti stanno lavorando, perché ho già scritto nel test tramite il repository iniettato nel database e ottenere tramite HTTP. Quindi il problema è l'importazione via dbunit, che non funziona ... Ho già usato dbunit con successo in un vecchio progetto, ma non insieme con l'avvio a molla. Forse gli ascoltatori di esecuzione non funzionano in modo simile allo spring boot?

Ho eseguito il debug delle classi di dbunit e letto tutto l'output del registro di debug, ma non capisco. DBUnit sta utilizzando il sorgente di avvio creato da dataSource (il precedente configurato), quindi è lo stesso database.

Quando si avvia i test di integrazione, il seguente è accaduto:
- liquibase crea lo schema del database in base alla configurazione liquibase
- DBUnit inserire nel database (dice il registro (forse JPA già spinto lo schema prima?) uscita e il debugging)
- Get 404 non trovato (torno a 404 quando nessun articolo è stato trovato nel database con il dato ID)

Aggiornamento:

sto cercando un alt ernativo a dbunit, ma non riesce a trovare alcuna buona soluzione. Quindi, come si prepara il database per i test di integrazione? In realtà ho solo bisogno di importare i dati individuali prima di ogni test o test se i dati sono persistenti come previsto.

Aggiornamento:

io uso le seguenti opzioni per la connessione al database h2:.

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

Quando ho tolto lo spring.datasource completa * primavera configurazione sta creando l'origine dati con valori standard e avviare un server di database h2 in memoria. Questo sarà fatto senza le opzioni che ho citato e ottengo un valore org.hibernate.PessimisticLockException perché dbunit blocca ancora la tabella del database e la richiesta HTTP che è stata inviata all'interno del test, non ha accesso alla tabella del database. Ciò è dovuto all'opzione MVCC=true; che ha aggiunto maggiore concorrenza, qual è in sostanza il problema, perché non sono presenti dati: "Solo connessioni 'vedi' dati impegnati e proprie modifiche". Quando si accede al database tramite la richiesta HTTP, i dati di dbunit non sono presenti, perché i dati di dbunit non sono impegnati per la connessione a molla ...

Quindi, qualcuno sa perché le tabelle del database h2 (e anche il derby) sono bloccate da dbunit?

risposta

5

Ho finalmente trovato una soluzione per questo problema.

Era la direzione giusta con lo PessimisticLockException dove ho indicato. DBUnit non ha rilasciato la connessione al database, ecco perché la connessione da primavera non ha potuto accedere alle tabelle del database che sono state bloccate.

Ho implementato la mia operazione di database. Ho usato l'opzione per customize DBUnit database options.

Prima di tutto ho implementato una classe denominata AutoCommitTransactionOperation in base alla TransactionOperation di DBUnit, con la differenza che ho rimosso il controllo jdbcConnection.getAutoCommit() == false e salvato l'auto commettere valore prima di commit automatico su false. Dopo il commit ho impostare il valore al valore salvato, di avere lo stesso stato come prima:

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); 
     } 
    } 
} 

Poi ho creato il DatabaseLookup.

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); 
    } 
} 

e ha aggiunto alla mia classe di test:

@DbUnitConfiguration(databaseOperationLookup = AutoCommitTransactionDatabaseLookup.class) 

Non sono sicuro se questo altro incidere ... alcun suggerimento al mio mod?

+0

Trovo magnifico che tu abbia condiviso la tua soluzione con una tale quantità di dettagli. Credo di aver incontrato lo stesso problema sul lavoro, sebbene nel mio progetto fittizio a casa funzioni sia con che senza la tua soluzione. Lo proverò al lavoro lunedì, questo è sicuro. –

+0

Grazie! Hai lo stesso problema? – David

Problemi correlati