2014-10-07 17 views
5

में अनुरोध करते समय डेटा आयात या मौजूदा नहीं किया जा सकता है यदि मैं निम्नलिखित सेटअप के साथ dbunit चलाता हूं और एकीकरण परीक्षण में HTTP के माध्यम से डेटा का अनुरोध करता हूं, तो मुझे कोई डेटा नहीं मिला क्योंकि डेटाबेस नहीं है खाली। डीबीयूनीट डेटाबेस को डेटा लिखता है, लेकिन जब मैं HTTP के माध्यम से डेटा का अनुरोध करता हूं तो यह खाली होता है।डीबीयूनीट और स्प्रिंग बूट - एकीकरण परीक्षण

यह मेरा सेटअप है: वसंत बूट-स्टार्टर-वेब (टॉमकैट को छोड़कर) के साथ वसंत बूट 1.1.7, वसंत-बूट-स्टार्टर-जेट्टी, वसंत-बूट-स्टार्टर-डेटा-जेपीए, वसंत-बूट- स्टार्टर-परीक्षण, liquibase कोर, dbunit 2.5.0, वसंत-परीक्षण dbunit 1.1.0

मुख्य आवेदन वर्ग:

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

टेस्ट विन्यास (आवेदन-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 

इंटीग्र राशन परीक्षण:

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

मैं और यहाँ सब कुछ पोस्ट कर सकता, संस्थाओं, भंडार, नियंत्रक, ... लेकिन इन घटकों की तरह काम कर रहे हैं, क्योंकि मैं पहले से ही डेटाबेस के लिए इंजेक्शन भंडार के माध्यम से परीक्षण में लिख सकते हैं और प्राप्त यह HTTP के माध्यम से। तो समस्या dbunit के माध्यम से आयात है, जो काम नहीं कर रहा है ... मैंने पहले से ही पुराने प्रोजेक्ट में सफलतापूर्वक dbunit का उपयोग किया है, लेकिन वसंत बूट के साथ नहीं। शायद निष्पादन श्रोताओं वसंत बूट के समान नहीं काम कर रहे हैं?

मैंने डीबगिट की कक्षाओं को डीबग किया और सभी डीबग लॉग आउटपुट को पढ़ा, लेकिन मुझे यह नहीं मिला। डीबीयूनीट वसंत बूट निर्मित डेटा स्रोत (उपरोक्त कॉन्फ़िगर किया गया) का उपयोग कर रहा है, इसलिए यह वही डेटाबेस है।

जब एकीकरण परीक्षण शुरू करने के लिए, निम्न होता है:
- liquibase liquibase विन्यास के आधार पर डेटाबेस स्कीमा बनाता
- डेटाबेस में डालने DBUnit (लॉग कहते हैं (शायद जेपीए पहले से ही से पहले स्कीमा धक्का दे दिया?) उत्पादन और डिबगिंग)
- 404 जाओ नहीं मिला (मैं 404 जब कोई प्रवेश) की गई ID वाला डेटाबेस में नहीं मिला था

अद्यतन:

मैं एक ऑल्ट के लिए खोज कर रहा हूँ dbunit करने के लिए ernative, लेकिन कोई अच्छा समाधान नहीं मिल सकता है। तो आप अपने एकीकरण परीक्षण के लिए अपना डेटाबेस कैसे तैयार करते हैं? असल में मुझे केवल प्रत्येक परीक्षण या परीक्षण से पहले व्यक्तिगत डेटा आयात करने की आवश्यकता है यदि डेटा अपेक्षित रूप से जारी रहता है।

अद्यतन:

मैं इन विकल्पों का उपयोग h2 डेटाबेस से कनेक्ट करने के लिए:।

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

जब मैं पूरा spring.datasource हटाया मानक मूल्यों के साथ डेटा स्रोत * विन्यास वसंत पैदा कर रही है और एक मेमोरी एच 2 डेटाबेस सर्वर शुरू करें। यह मेरे द्वारा उल्लिखित विकल्पों के बिना किया जाएगा और मुझे org.hibernate.PessimisticLockException मिल जाएगा क्योंकि dbunit अभी भी डेटाबेस तालिका को लॉक करता है और HTTP अनुरोध जो परीक्षण के अंदर भेजा गया था, डेटाबेस तालिका तक कोई पहुंच नहीं है। यह MVCC=true; विकल्प के कारण है जो उच्च समेकन को जोड़ता है, मूल रूप से समस्या क्या है, क्यों कोई डेटा मौजूद नहीं है: "कनेक्शन केवल 'प्रतिबद्ध डेटा देखते हैं, और स्वयं के परिवर्तन"। HTTP अनुरोध के माध्यम से डेटाबेस तक पहुंचने पर, dbunit का डेटा मौजूद नहीं है, क्योंकि dbunit का डेटा वसंत कनेक्शन के लिए प्रतिबद्ध नहीं है ...

तो, क्या किसी को पता है कि क्यों H2 (और भी डर्बी) डेटाबेस तालिका dbunit द्वारा बंद कर दी गई है?

उत्तर

5

मुझे अंततः इस मुद्दे के लिए एक समाधान मिला।

यह PessimisticLockException के साथ सही दिशा थी जहां मैंने इंगित किया था। डीबीयूनीट ने डेटाबेस कनेक्शन जारी नहीं किया, यही कारण है कि वसंत से कनेक्शन डेटाबेस तालिका (खातों) तक नहीं पहुंच सका जहां लॉक किया गया था।

मैंने अपना खुद का डेटाबेस ऑपरेशन लागू किया। मैंने customize DBUnit database options पर विकल्प का उपयोग किया।

सबसे पहले मैं अंतर यह है कि मैं चेक jdbcConnection.getAutoCommit() == false हटा दिया और बचाया ऑटो ऑटो झूठा के लिए प्रतिबद्ध सेट करने से पहले मूल्य के लिए प्रतिबद्ध के साथ एक कक्षा DBUnit की TransactionOperation के आधार पर AutoCommitTransactionOperation कहा जाता है लागू किया,। प्रतिबद्ध बाद मैं मूल्य वापस बचाया मान पर सेट है, जैसे पहले की तरह ही राज्य के लिए:

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

तब मैं 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); 
    } 
} 

और अपने परीक्षण वर्ग के लिए यह कहा:

@DbUnitConfiguration(databaseOperationLookup = AutoCommitTransactionDatabaseLookup.class) 

मुझे यकीन है कि अगर यह अधिक हैक नहीं कर रहा हूँ ... मेरी हैक करने के लिए कोई संकेत?

+0

मुझे यह बिल्कुल शानदार लगता है कि आपने इस तरह के विस्तार में अपना समाधान साझा किया है। मेरा मानना ​​है कि मैं काम पर एक ही समस्या में भाग गया, हालांकि घर पर अपनी खुद की डमी परियोजना में यह आपके समाधान के साथ और बिना दोनों काम करता है। मैं सोमवार को काम पर कोशिश करूंगा, यह निश्चित रूप से है। –

+0

धन्यवाद! क्या आपकी भी यही समस्या है? – David

संबंधित मुद्दे