2016-01-22 5 views
6

मैं अपने उत्पादों में से एक के लिए यूनिट परीक्षण लिख रहा हूं और एंटीटी फ्रेमवर्क से कनेक्शन को सफलतापूर्वक नकल करने के लिए एमओक का उपयोग किया गया है। हालांकि, मैं निम्नलिखित विधि में आया हूं:Moq और SqlConnection?

public static productValue findValues(string productName, string dbConnectionString) 
{ 
    try 
    { 
     SqlConnection conn = new SqlConnection(dbConnectionString); 
     conn.Open(); 
     //Do stuff 
    } 
} 

जो पास किए गए कनेक्शन स्ट्रिंग का उपयोग करके उस विधि के अंदर हमारे डेटाबेस तक पहुंचता है। क्या एमओक का उपयोग करके एक नकली डीबी स्थापित करना और कनेक्शन स्ट्रिंग बनाना संभव है जो मॉक किए गए डीबी को इंगित करता है? मैं हालांकि मैं अनिश्चित हूँ अगर यह सही दृष्टिकोण है, के रूप में इस संबंध में ही बजाय डीबी नकली हैं

var mockSqlConnnection = new Mock<SqlConnection>(); 

की तर्ज पर कुछ कर रही कोशिश कर रहा है।

+1

यह संभव नहीं है कि मेरा मानना ​​है कि एसक्यूएलकनेक्शन एक मुहरबंद वर्ग है और इसलिए इसे मजाक नहीं किया जा सकता है। आप आईडीबीसी कनेक्शन का नकल कर सकते हैं, लेकिन अभी भी बहुत कुछ करना होगा: यदि आप इस विधि का परीक्षण करना चाहते हैं, तो आपको इसे थोड़ा सा रिफैक्टर करना पड़ सकता है। – stuartd

+1

आप बिल्कुल सही हैं, एसक्यूएलकनेक्शन एक सीलबंद वर्ग – Novastorm

+1

है [डेटाबेस को आपके रास्ते से बाहर निकालने का सबसे अच्छा तरीका है सारणी इंटरफेस के पीछे डेटा एक्सेस को छिपाना है जिसे व्यवसाय तर्क परीक्षण में मजाक किया जा सकता है] (http: // codebetter .com/jeremymiller/2005/10/12/इकाई परीक्षण-व्यवसाय-तर्क-बिना-ट्रिपिंग-ओवर-द-डेटाबेस /)। – dee

उत्तर

3

मैं एक ऐसी ही समस्या थी।

class SqlDataContext : ISqlDataContext { 

    private readonly SqlConnection _connection; 

    public SqlDataContext(string connectionString) 
    { 
     _connection = CreateConnection(connectionString); 
    } 

    public IDataReader ExecuteReader(string storedProcedureName, ICollection<SqlParameter> parameters) 
    { 
     // execute the command here using the _connection private field. 
     // This is where your conn.Open() and "do stuff" happens. 
    } 

    private SqlConnection CreateConnection(string connectionString) 
    { 
     if (string.IsNullOrEmpty(connectionString)) 
     { 
      throw new ArgumentNullException("connectionString"); 
     } 

     return new SqlConnection(connectionString); 
    } 
} 

interface ISqlDataContext 
{ 
    IDataReader ExecuteReader(string storedProcedureName, ICollection<SqlParameter> parameters); 
} 

आप के रूप में आप की जरूरत है ISqlDataContext के भार के जोड़ सकते हैं:

मैं SqlConnection के चारों ओर एक SqlDataContext आवरण से दूर और ISqlDataContext इंटरफ़ेस विरासत में मिला है की शुरुआत की।

इसका क्या अर्थ है कि आप एमक्यू या समान और वापसी नकली मानों का उपयोग करने के लिए ISqlDataContext को नकल कर सकते हैं।

मतलब है कि आप अपने भंडार या किसी और चीज का परीक्षण कर सकते हैं जो एसक्यूएलकनेक्शन के माध्यम से डेटाबेस को हिट करता है, वास्तव में डेटाबेस को हिट किए बिना।

दूसरा लाभ यह है कि आप आवश्यकतानुसार डीआई/आईओसी के साथ आईएसक्लॉन्टेक्स्ट इंजेक्ट कर सकते हैं।

+0

शानदार! मैं इसे – Novastorm

+2

पर दूंगा, जबकि यह कार्यान्वयन आपको IDataReader के निर्माण की नकल करने देगा, अब आपके पास एक रिसाव कार्यान्वयन है जिसके परिणामस्वरूप "पूल से कनेक्शन प्राप्त करने में असमर्थ" (http: //stackoverflow.com/questions/15848239/how-to-solve-max-connection-pool-error)। ऐसा इसलिए है क्योंकि आप अपने SqlConnection (या SqlCommand) को "निपटान" नहीं कर रहे हैं। मैं IDISposable इंटरफेस को लागू करने की भी सिफारिश करता हूं (https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx) और अपने उपयोग के आस-पास "उपयोग" कथन डालना यह SqlDataContext ऑब्जेक्ट। – Sean

0

Repository Pattern पर एक नज़र डालें, अनिवार्य रूप से आप डेटाबेस से बात करने के कार्यान्वयन के बारे में चिंता करने के बजाय, अपने उपभोग करने वाले वर्गों में डेटा का नकल करेंगे।

public class StudentController : Controller 
    { 
     private IStudentRepository studentRepository; 

     public StudentController(IStudentRepository studentRepository) 
     { 
     this.studentRepository = studentRepository; 
     } 

और के रूप में प्रयोग किया है::

public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page) 
    { 
    var students = from s in studentRepository.GetStudents() 
        select s; 

पूर्ण उदाहरण


अनिवार्य रूप से, आप एक भंडार

namespace ContosoUniversity.DAL 
{ 
    public class StudentRepository : IStudentRepository, IDisposable 
    { 
     private SchoolContext context; 

     public StudentRepository(SchoolContext context) 
     { 
      this.context = context; 
     } 

     public IEnumerable<Student> GetStudents() 
     { 
      return context.Students.ToList(); 
     } 

     // ... more 

कौन सा तो अन्य वर्गों में सेवन किया जाता है के लिए होता है शीर्ष पर लिंक में है।


तो फिर आप अपने वर्ग में एक मज़ाक उड़ाया भंडार से होकर गुजरेगा:

// arrange 
var mockedRepo = new Mock<IStudentRepository>(); 
// configure 

// act 
var controller = new StudentController(mockedRepo.Object); 
// do stuff 

// assert 
+0

यदि वह किसी वर्ग या विधि का परीक्षण करना चाहता है जो सीधे कनेक्शन का उपयोग करता है क्योंकि मुझे विश्वास है कि वह तब है तो वह कठिनाइयों में भाग लेगा। ऐसा लगता है कि वह जिस विधि का परीक्षण कर रहा है वह वैसे भी एक भंडार विधि है। – Graham

+0

अगर वह भंडार का परीक्षण करना चाहता है? – chris31389

0

देर लेकिन MSTest साथ क्यों नहीं:

[TestMethod] 
MyTestWithInternSqlConnection() 
{ 
    using (ShimsContext.Create()) 
    { 
     // simulate a connection 
     ShimSqlConnection.AllInstances.Open = connection => { }; 
     string commandText; 

     // shim-Mock all called methods 
     ShimSqlCommand.AllInstances.ExecuteReader = command => 
     { 
     commandText = command.CommandText; 
     return new ShimSqlDataReader(); 
     }; 

     int readCount = 0; 
     ShimSqlDataReader.AllInstances.Read = reader => readCount == 0; 
     ShimSqlDataReader.AllInstances.GetSqlStringInt32 = (reader, i) => 
     { 
     readCount++; 
     return "testServer"; 
     }; 

     var theReadedString = AMethodUnderTestThatReadsFromDatabaseAString(); 
     Assert.IsTrue(theReadedString == "testServer"); 
    } 
} 

आप System.Data के लिए एक संदर्भ जोड़ने और फिर इसके लिए एक नकली जोड़ने की जरूरत है।

https://msdn.microsoft.com/en-us/library/hh549175.aspx बेहतर है, अगर आप कार्यान्वयन बदलते हैं और आप उपयोग की गई पढ़ी परत को बदल सकते हैं लेकिन ...