2011-12-02 18 views
7

मैं कुछ लेखापरीक्षित इकाइयों के आसपास कुछ परीक्षण बनाने की कोशिश कर रहा हूं। मेरी समस्या यह है कि लेनदेन प्रतिबद्धता पर केवल लेखा परीक्षा में प्रवेश करता है।हाइबरनेट के साथ एकीकरण परीक्षण

मुझे कुछ परीक्षण वस्तुओं को बनाने/संपादित करने, लेनदेन करने और फिर संशोधन की जांच करने की आवश्यकता है।

एनवर्स के साथ एकीकरण परीक्षण के लिए सबसे अच्छा तरीका क्या है?

अद्यतन: यहाँ मैं क्या हासिल करना चाहते का एक बहुत बुरा, गैर नियतात्मक परीक्षण क्लास है। मैं परीक्षण तरीकों

पहले एकल लेन-देन में एक खाता और account_transaction बनाने के आदेश पर निर्भर रहे बिना यह करने के लिए पसंद करेंगे। दोनों लेखा परीक्षित प्रविष्टियों संशोधन 1.

दूसरा एक नया लेनदेन में account_transaction अद्यतन के लिए कर रहे हैं। लेखा परीक्षा प्रवेश संशोधन पर 2.

तीसरा है, संशोधन 1 पर लेखा परीक्षित खाते लोड और इसके साथ कुछ करना।

@Transactional 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"/testApplicationContext.xml"}) 
public class TestAuditing { 

    @Autowired 
    private AccountDao accountDao; 

    @PersistenceContext 
    private EntityManager entityManager; 

    @Test 
    @Rollback(false) 
    public void first() { 
     Account account = account("Test Account", "xxxxxxxx", "xxxxxx"); 

     AccountTransaction transaction = transaction(new Date(), Deposit, 100, "Deposit"); 
     account.setTransactions(newArrayList(transaction)); 

     accountDao.create(account); 
    } 

    @Test 
    @Rollback(false) 
    public void second() { 
     Account account = accountDao.getById(1L); 
     AccountTransaction transaction = account.getTransactions().get(0); 
     transaction.setDescription("Updated Transaction"); 
     accountDao.update(account); 
    } 

    @Test 
    public void third() { 
     AuditReader reader = AuditReaderFactory.get(entityManager); 

     List<Number> accountRevisions = reader.getRevisions(Account.class, 1L); 
     //One revision [1] 

     List<Number> transactionRevisions = reader.getRevisions(AccountTransaction.class, 1L); 
     //Two revisions [1, 2] 

     Account currentAccount = accountDao.getById(1L); 
     Account revisionAccount = (Account) reader.createQuery().forEntitiesAtRevision(Account.class, 1).getSingleResult(); 

     System.out.println(revisionAccount); 
    } 
+1

जांचें [यह] (http://nurkiewicz.blogspot.com/2011/11/spring-pitfalls-transactional-tests.html) बाहर - लापरवाह आत्म-प्रचार। –

+0

उत्तर टॉमसज़ के लिए धन्यवाद, मुझे अभी भी यकीन नहीं है कि आपकी ब्लॉग पोस्ट से मेरी समस्या का समाधान कैसे करें। मुझे आलसी लोडिंग आदि से झूठी सकारात्मकताओं में वास्तव में कोई समस्या नहीं है, वास्तव में कुछ ऑडिटिंग परीक्षण डेटा सेट करने के लिए कुछ लेन-देन करने के साथ। हो सकता है कि मैंने आपकी पोस्ट में कुछ स्पष्ट याद किया हो? –

+1

ठीक है, मेरे आलेख को 'डीबीआरसेट रूट' पर स्क्रॉल करें - मेरा विचार है कि '@ ट्रांजेक्शनल' जुनीट परीक्षणों का उपयोग करने से बचें और बस अपना कोड प्रतिबद्ध करें और रोलबैक लेनदेन दें। जाहिर है यह परीक्षण दोहराया जा सकता है और नाजुक। लेकिन परिवर्तनों को वापस लाने की बजाय मैं डेटाबेस को डंप करने और प्रत्येक परीक्षण के पहले/बाद में इसे बहाल करने का प्रस्ताव कर रहा हूं। कोड स्कैला में है, लेकिन यह सिर्फ एक सामान्य विचार है। अगर आप यही चाहते हैं तो मुझे बताएं ताकि मैं अलग जवाब में थोड़ा और विस्तार कर सकूं। –

उत्तर

3

टॉमसज़ के सुझाव के अनुसार मैंने प्रत्येक दाओ ऑपरेशन के बाद काम करने के लिए एक लेनदेन टेम्पलेट का उपयोग किया। कोई कक्षा-स्तर @ ट्रान्सएक्शनल एनोटेशन नहीं है।

envers लेखा परीक्षा प्रविष्टियों विधि खत्म होने से पहले डाला जाता है जो है मैं सिर्फ क्या जरूरत है।

@ContextConfiguration("testApplicationContext.xml") 
public class TestAuditing extends AbstractJUnit4SpringContextTests { 

    @Autowired 
    private PlatformTransactionManager platformTransactionManager; 

    @Autowired 
    private PersonDao personDao; 

    private TransactionTemplate template; 

    @Before 
    public void transactionTemplate() { 
     template = new TransactionTemplate(platformTransactionManager); 
    } 

    @Test 
    public void test() { 
     Person person = createInTransaction(person("Karl", "Walsh", address("Middle of nowhere")), personDao); 
     System.out.println(person); 
    } 

    private <T> T createInTransaction(final T object, final Dao<?, T> dao) { 
     return template.execute(new TransactionCallback<T>() { 
      public T doInTransaction(TransactionStatus transactionStatus) { 
       dao.create(object); 
       return object; 
      } 
     }); 
    } 
} 
4

मैं जो वापस परीक्षण रोल जब उनके किया वसंत के लेन-देन परीक्षण समर्थन की एक उपयोगकर्ता हूँ, और envers की डिजाइन के कारण, संशोधन नहीं बनाई गई हैं। मैंने एक हैक बनाया जो लेनदेन करने से पहले मैन्युअल रूप से अपने काम करने के लिए "बताना" करने की इजाजत देता है, लेकिन वसंत को रोलबैक जारी रखने की अनुमति देता है।

इन स्निपेट्स को मदद करनी चाहिए। 1. अपना स्वयं का ऑडिटलिस्टर बनाएं जो मौजूदा एनवर्ड्स ऑडिट श्रोता को ओवरराइड करता है। यह यूनिट परीक्षणों के लिए दृश्यमान स्थिर सदस्य तक पहुंच की अनुमति देता है। शायद एक बेहतर तरीका है, लेकिन यह काम करता है।

public class AuditEventListenerForUnitTesting extends AuditEventListener { 

    public static AuditConfiguration auditConfig; 

    @Override 
    public void initialize(Configuration cfg) { 
     super.initialize(cfg); 
     auditConfig = super.getVerCfg(); 
    } 
} 

envers द्वारा प्रदान की एक के बजाय इस नए श्रोता वर्ग को शामिल कर अपनी persistence.xml संशोधित

अब "इकाई" परीक्षण के भीतर (अन्य श्रोताओं के लिए यदि आवश्यक हो तो दोहराने):

{ 
    saveNewList(owner); //code that does usual entity creation 
    em.flush(); 
    EventSource hibSession = (EventSource) em.getDelegate(); 
    AuditEventListenerForUnitTesting.auditConfig.getSyncManager().get(hibSession).doBeforeTransactionCompletion(hibSession);  
    //look for envers revisions now, and they should be there 
} 

मुझे इसकी आवश्यकता है क्योंकि मेरे पास हाइबरनेट इकाइयों के खिलाफ कुछ जेडीबीसी प्रश्न संस्करण संस्करणों में शामिल हो गए हैं।

0

दो अन्य समाधान मेरे लिए काम नहीं किया था, इसलिए मैं एक और तरीका इस्तेमाल किया, मैं सिर्फ एक नया लेन-देन बना सकते हैं और मजबूर करते हैं। हर बार मुझे एक नया संशोधन की ज़रूरत है, मैं इसे फिर से करता हूं।

@Autowired 
@Qualifier("transactionManager") 
private PlatformTransactionManager platformTransactionManager; 

@Test 
public void enversTest() throws Exception{ 
    Entity myEntity = new Entity(); 

    TransactionStatus status = platformTransactionManager.getTransaction(new DefaultTransactionDefinition()); 
    myEntity.setName("oldName"); 
    myEntity = entityDao.merge(myEntity); 
    platformTransactionManager.commit(status); // creates a revision with oldname 

    TransactionStatus newStatus = platformTransactionManager.getTransaction(new DefaultTransactionDefinition()); 
    myEntity.setName("newName"); 
    myEntity = entityDao.merge(myEntity); 
    platformTransactionManager.commit(newStatus); // creates a new revision with newName 
} 

आप @Transactional(transactionManager="transactionManager") का उपयोग करते हैं, लेकिन यह करता बाईपास और एक लेन-देन के रूप में प्रत्येक परीक्षा पर विचार हो सकता है (इस प्रकार एक ही परीक्षण के भीतर कई समय versionning नहीं ...)

2

यह दृढ़ता से this previous answer के लिए अनुकूलित से प्रेरित है Envers 4.2.19 के साथ काम करें। अंतिम (जेपीए 2.0)।इस समाधान को लेनदेन की आवश्यकता नहीं है, जो मेरे मामले में एक आवश्यकता थी।

पहले org.hibernate.integrator.spi.Integrator के निम्नलिखित कार्यान्वयन बना सकते हैं और classpath में जोड़ें:

public class MyIntegrator implements Integrator { 

    public static AuditConfiguration auditConfig; 

    @Override 
    public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, 
    SessionFactoryServiceRegistry serviceRegistry) { 
    auditConfig = AuditConfiguration.getFor(configuration); 
    } 

    @Override 
    public void integrate(MetadataImplementor metadata, SessionFactoryImplementor sessionFactory, 
    SessionFactoryServiceRegistry serviceRegistry) { 
    // NOP 
    } 

    @Override 
    public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { 
    // NOP 
    } 

} 

तो src/test/resources के तहत एक META-INF/services/org.hibernate.integrator.spi.Integrator फ़ाइल बनाने और इसे में एकीकरण वर्ग की पूरी तरह से QULIFIED नाम पेस्ट करें।

अपने परीक्षण में,, अपने डीएओ विधि कॉल हाइबरनेट सत्र फ्लश और आगे बढ़ने के लिए Envers बता के बाद यह किया है:

EventSource es = (EventSource) entityManager.getDelegate(); 
SessionImplementor si = entityManager.unwrap(SessionImplementor.class); 
MyIntegrator.auditConfig.getSyncManager().get(es).doBeforeTransactionCompletion(si); 

आप तो अपने डीबी की सामग्री के परीक्षण कर सकते हैं और अंत में लेन-देन रोलबैक।

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