2016-08-15 6 views
6

अतीत में जब मैं यूनिट परीक्षण लागू कर रहा हूं, मैंने डेटा एक्सेस परतों के लिए 'सभ्य' इकाई परीक्षण स्थापित करने के लिए संघर्ष किया है क्योंकि उनके पास अक्सर बाहरी निर्भरता के रूप में डेटाबेस होता है। एक आदर्श दुनिया में मैं संग्रहीत प्रक्रिया कॉल का नकल करता हूं ताकि बाह्य निर्भरता हटा दी जा सके।सी # इकाई परीक्षण, संग्रहीत प्रक्रिया का मजाक

हालांकि मैं एमओक्यू मॉकिंग फ्रेमवर्क के साथ ऐसा करने के लिए काम करने में असमर्थ रहा हूं, या इसका समर्थन करने वाले किसी अन्य ढांचे को ढूंढने में असमर्थ हूं। इसके बजाय मैंने ज्ञात डेटा के साथ एक स्क्रिप्टेड टेस्ट डेटाबेस बनाने के लिए वापस कर दिया है (ताकि मैं हमेशा आउटपुट प्राप्त कर सकूं) लेकिन यह उस परत को मॉक करने से थोड़ा अलग है।

क्या कोई भी डेटा एक्सेस लेयर के इस हिस्से को नकल करने का सुझाव दे सकता है [मुझे एंटिटी फ्रेमवर्क के बारे में पता है कि https://effort.codeplex.com/ मौजूद है]?


विस्तार उदाहरण के लिए अगर मैं कैसे मैं संग्रहीत प्रक्रिया उत्पादन ताकि SQLDataReader निर्दिष्ट डेटा शामिल हैं नकली है तो निम्न विधि

public object RunStoredProc() 
{ 
    //Some Setup 

    using (SqlConnection conn = new SqlConnection(CONNNECTION_STRING)) 
    { 
     using (SqlCommand comm = new SqlCommand("storedProcName", conn)) 
     { 
      conn.Open(); 
      comm.CommandType = CommandType.StoredProcedure; 
      using (SqlDataReader reader = comm.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        //Logic 
       } 
      } 
     } 
    } 

    //Return object based on logic 
} 

है। उच्च स्तर पर मैं RunStoredProc() विधि का नकल कर सकता हूं - लेकिन इससे मुझे यह जांचने में मदद नहीं मिलेगी कि उस विधि में तर्क सही है या नहीं। वैकल्पिक रूप से मैं SQLReader बाहर किसी अन्य विधि में पट्टी सकता

public object RunStoredProc() 
{ 
    //Some Setup 

    List<object> data = GetData(); 
    //Logic 

    //Return object based on logic 
} 

private List<object> GetData() 
{ 
    using (SqlConnection conn = new SqlConnection(CONNNECTION_STRING)) 
    { 
     using (SqlCommand comm = new SqlCommand("storedProcName", conn)) 
     { 
      conn.Open(); 
      comm.CommandType = CommandType.StoredProcedure; 
      using (SqlDataReader reader = comm.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        //place into return object 
       } 
      } 
     } 
    } 
} 

लेकिन उन्होंने 'GetData' विधि निजी (प्रकाशित इंटरफ़ेस का हिस्सा नहीं) मैं तो उस उपहास करने के लिए सक्षम नहीं होगा होना चाहिए और इसलिए इस मुद्दे को अवशेष ।

उत्तर

3

मुझे लगता है कि हम की जरूरत है, ताकि वे मज़ाक उड़ाया और निर्भरता इंजेक्शन के साथ इस्तेमाल किया जा सकता सार करते हैं उन सभी इंटरफेस (IDbConnection, IDbTransaction, IDbCommand, IDataReader) और एफई (IDbConnectionFactory) से एक विचार उधार लेने की है। मुझे लगता है कि SqlConnection और बाकी एक कार्यान्वयन विस्तार के अधिक हैं और सारणित किया जा सकता है।

एक विचार इकाई की रूपरेखा से आप एक कनेक्शन कारखाना

public interface IDbConnectionFactory { 
    /// <summary> 
    /// Creates a connection based on the given database name or connection string. 
    IDbConnection CreateConnection(string nameOrConnectionString); 
} 

बना सकते हैं और तुम तो केवल कपोल-कल्पना का उपयोग करने के अपने उदाहरण विधि refactor कर सकते हैं के बाद।

public class MyDataAccessClass { 
    private IDbConnectionFactory dbConnectionFactory; 
    private string CONNNECTION_STRING = "Connection string here"; 

    public MyDataAccessClass(IDbConnectionFactory dbConnectionFactory) { 
     this.dbConnectionFactory = dbConnectionFactory; 
    } 

    public object RunStoredProc() { 
     //Some Setup 
     List<object> result = new List<object>(); 

     using (IDbConnection conn = dbConnectionFactory.CreateConnection(CONNNECTION_STRING)) { 
      using (IDbCommand comm = conn.CreateCommand()) { 
       comm.CommandText = "storedProcName"; 
       conn.Open(); 
       comm.CommandType = CommandType.StoredProcedure; 
       using (IDataReader reader = comm.ExecuteReader()) { 
        while (reader.Read()) { 
         //...Logic to populate result 
        } 
       } 
      } 
     } 

     //Return object based on logic 
     return result; 
    } 
} 

वहां से आप अपनी पसंद के मजाक ढांचे का उपयोग कर इंटरफेस नकली या इंजेक्षन और अपने विधि का परीक्षण करने के अपने स्वयं के नकली पैदा करते हैं।

[TestClass] 
public class StoredProcedureUnitTest { 
    [TestMethod] 
    public void TestRunStoredProc() { 
     //Arrange 
     var connectionFactory = new Mock<IDbConnectionFactory>(); 
     //..Setup... 

     var sut = new MyDataAccessClass(connectionFactory.Object); 

     //Act 
     var actual = sut.RunStoredProc(); 

     //Assert 
     //... 
    } 
} 
+0

धन्यवाद, लगता है कि यह काम करेंगे, अगर मैं इस सही ढंग से केवल विधि मैं उपहास करने के लिए IDbCommand.ExecuteReader() होगा आवश्यकता होगी पढ़ रहा हूँ [मैं भी करने के लिए IDbConnection.CreatCommand उपहास करने के लिए आवश्यकता होगी मॉक आईडीबी कॉमांड वापस करें लेकिन यह छोटा होना चाहिए]। अगर किसी और के पास कोई अन्य विचार है तो मैं थोड़ी देर के लिए खुला प्रश्न छोड़ने जा रहा हूं। –

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