2011-04-14 19 views
8

पर एनएचबीर्नेट के साथ परीक्षण करते समय यादृच्छिक त्रुटि मेरे पास एक प्रणाली है जो संदेश प्राप्त करने के बाद - इसे एक टेबल पर लिखती है, और एक और प्रक्रिया डीबी को प्रसंस्करण के लिए छोड़ देती है। मेरे स्वचालित परीक्षणों में मैंने एक ही प्रक्रिया में परिचालनों को विलय कर दिया है, लेकिन दो परिचालनों से एनएच सत्रों को विलय (अवधारणात्मक रूप से) नहीं कर सकता।एन-मेमोरी एसक्यूएलएट डीबी

स्वाभाविक रूप से - समस्याएं उत्पन्न होती हैं।

मैंने परीक्षण दुनिया में काम करने के लिए SQLite-InMemory-NHibernate संयोजन प्राप्त करने के बारे में सबकुछ पढ़ा है, लेकिन अब मैं "ऐसी कोई तालिका" त्रुटियों के कारण, RANDOMLY विफल परीक्षणों में भाग गया हूं। इसे स्पष्ट करने के लिए - "यादृच्छिक" का अर्थ है कि एक ही सटीक विन्यास और कोड के साथ एक ही परीक्षण कभी-कभी विफल हो जाएगा।

मैं निम्नलिखित SQLite विन्यास है:

return SQLiteConfiguration 
.Standard 
.ConnectionString(x => x.Is("Data Source=:memory:; Version=3; New=True; Pooling=True; Max Pool Size=1;")) 
.Raw(NHibernate.Cfg.Environment.ReleaseConnections, "on_close"); 

अपने परीक्षण (हर परीक्षण) मैं "स्थिर" सत्र प्रदाता लाने की शुरुआत में, और कृपया यह पूछना मौजूदा डीबी साफ फ्लश, और पुनः बनाना स्कीमा:

public void PurgeDatabaseOrCreateNew() 
{ 
    using (var session = GetNewSession()) 
    using (var tx = session.BeginTransaction()) 
    { 
      PurgeDatabaseOrCreateNew(session); 
      tx.Commit(); 
    } 
} 

private void PurgeDatabaseOrCreateNew(ISession session) 
{ 
    //http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx 
    new SchemaExport(_Configuration) 
     .Execute(false, true, false, session.Connection, null); 
} 

तो हाँ, यह एक अलग सत्र पर है, लेकिन कनेक्शन SQLite पर जमा है, इसलिए अगले सत्र मैं बनाने उत्पन्न स्कीमा देखेंगे। फिर भी, जबकि अधिकांश बार यह काम करता है - कभी-कभी बाद में "एनक्यू" ऑपरेशन विफल हो जाएगा क्योंकि यह मेरे आने वाले संदेशों के लिए एक टेबल नहीं देख सकता है। इसके अलावा - ऐसा लगता है कि प्रति परीक्षण सूट चलाने में अधिकतम एक या दो बार होता है; सभी परीक्षण विफल नहीं हो रहे हैं, केवल पहले (और कभी-कभी एक और। यह सुनिश्चित नहीं है कि यह दूसरा है या नहीं)।

सबसे बुरा हिस्सा यादृच्छिकता है, स्वाभाविक रूप से। मैंने खुद से कहा है कि मैंने इसे कई बार ठीक कर दिया है, सिर्फ इसलिए कि यह बस "विफल रहा बंद" है। बिना सोचे समझे।

यह FW4.0, System.Data.SQLite x86 संस्करण, Win7 64b और 2008R2 (कुल में तीन differen मशीन), एनएच 2.1.2, एफएनएच के साथ कॉन्फ़िगर किया गया है, TestDriven.NET 32b प्रीसेस और एनयूनिट कंसोल 32 बी प्रक्रियाओं पर ।

सहायता?

+0

मुझे यह समस्या भी है। लगभग हर टेस्ट पास होता है, लेकिन एक बार में एक या दो परीक्षण "ऐसी कोई तालिका" त्रुटियों के साथ असफल हो जाएंगे, और यदि मैं उन्हें फिर से चलाता हूं, तो वे पास हो जाते हैं। मुझे लगता है कि यह सिर्फ SQLite कनेक्शन पूल में कनेक्शन को यादृच्छिक रूप से पुनर्निर्माण कर रहा है। –

उत्तर

8

हाय मुझे पूरा यकीन है कि आपके पास बिल्कुल वही समस्या है। मैं एकीकरण परीक्षण प्रति एकाधिक सत्र खोलता और बंद करता हूं। SQLite कनेक्शन पूलिंग और मेरे स्वयं के कुछ प्रयोगों के माध्यम से खोदने के बाद, मैं निम्नलिखित निष्कर्ष पर आया हूं:

SQLite पूलिंग कोड वीक रेफरेंस का उपयोग करके कनेक्शन को कैश करता है, जो संदर्भ के बाद से option नहीं है जब कनेक्शन के लिए कोई सामान्य (मजबूत) संदर्भ नहीं होता है और जीसी रन होता है तो कनेक्शन को साफ़ कर दिया जाएगा। चूंकि आप जीसी चलाते समय भविष्यवाणी नहीं कर सकते हैं, यह "यादृच्छिकता" बताता है। एक बंद करने और एक और सत्र खोलने के बीच GC.Collect(); को आजमाएं और अपना परीक्षण हमेशा असफल रहेगा।

मेरे समाधान उद्घाटन सत्र के बीच कनेक्शन अपने आप को कैश करने के लिए, इस तरह था:

public class BaseIntegrationTest 
{ 
    private static ISessionFactory _sessionFactory; 
    private static Configuration _configuration; 
    private static SchemaExport _schemaExport; 

    // I cache the whole session because I don't want it and the 
    // underlying connection to get closed. 
    // The "Connection" property of the ISession is what we actually want. 
    // Using the NHibernate SQLite Driver to get the connection would probably 
    // work too. 
    private static ISession _keepConnectionAlive; 

    static BaseIntegrationTest() 
    { 
     _configuration = new Configuration(); 
     _configuration.Configure(); 
     _configuration.AddAssembly(typeof(Product).Assembly); 
     _sessionFactory = _configuration.BuildSessionFactory(); 
     _schemaExport = new SchemaExport(_configuration); 

     _keepConnectionAlive = _sessionFactory.OpenSession(); 
    } 

    [SetUp] 
    protected void RecreateDB() 
    { 
     _schemaExport.Execute(false, true, false, _keepConnectionAlive.Connection, null); 
    } 

    protected ISession OpenSession() 
    { 
     return _sessionFactory.OpenSession(_keepConnectionAlive.Connection); 
    } 
} 

मेरी integrationtests से प्रत्येक इस वर्ग से विरासत, और OpenSession कॉल() एक सत्र प्राप्त करने के लिए। [SetUp] विशेषता के कारण प्रत्येक परीक्षण से पहले Nuateit द्वारा RecreateDB को बुलाया जाता है।

मुझे आशा है कि यह आपको या किसी अन्य व्यक्ति को यह त्रुटि प्राप्त करने में सहायता करेगी।

+0

SQLite के कैशिंग तंत्र को बदलना शायद सबसे साफ समाधान होगा, लेकिन मुझे अभी तक ऐसा करने में विश्वास नहीं है ;-) – dvdvorle

+0

यह ठीक है कि मैंने इसे कैसे हल किया। पहले समाधान पोस्ट न करने के लिए खेद है। – Arielr

0

केवल एक चीज जो ध्यान में आती है कि आप परीक्षण के बाद सत्र को यादृच्छिक रूप से छोड़ रहे हैं। आपको यह सुनिश्चित करना होगा कि किसी अन्य को खोलने से पहले कोई मौजूदा ISession बंद हो। यदि आप उपयोग() कथन का उपयोग नहीं कर रहे हैं या निपटान() को मैन्युअल रूप से कॉल कर रहे हैं तो सत्र कहीं भी उन यादृच्छिक अपवादों को जन्म दे सकता है।