2013-04-25 6 views
8

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

मैं संदर्भ

public interface ITestEntities 
{ 
    IDbSet<Order> Orders { get; } 
    IDbSet<Product> Products { get; } 
    IDbSet<User> Users { get; } 
} 
फिर

संदर्भ

public class TestEntities : DbContext, ITestEntities 
{ 
    public TestEntities() : base("name=TestEntities") 
    { 

    } 

    public virtual IDbSet<Order> Orders { get; set; } 
    public virtual IDbSet<Product> Products { get; set; } 
    public virtual IDbSet<User> Users { get; set; } 
} 

के लिए ITestEntities इंटरफेस हो एक नियंत्रक और एक कार्य Moq

का उपयोग कर

public class HomeController : Controller 
{ 
    private ITestEntities db; 

    public HomeController() 
    { 
     db = new TestEntities(); 
    } 

    public HomeController(ITestEntities db) 
    { 
     this.db = db; 
    } 

    public ActionResult Index() 
    { 
     var count = db.Users.Count(); 
     ViewBag.count = count; 

     return View(count); 
    }   
} 

और अंत में एक NUnit परीक्षण परीक्षण करने के लिए

[Test] 
public void ModelValueShouldBeTwo() 
{ 
    var mockUsers = new Mock<IDbSet<User>>(); 
    mockUsers.Setup(m => m.Count()).Returns(2); 

    var mockDB = new Mock<ITestEntities>(); 
    mockDB.Setup(db => db.Users).Returns((IDbSet<User>)mockUsers); 

    var controller = new HomeController((ITestEntities)mockDB); 

    var view = controller.Index(); 

    Assert.IsInstanceOf<ViewResult>(view); 
    Assert.AreEqual(((ViewResult)view).Model, 2); 
} 

समस्या इस पंक्ति के साथ है: mockUsers.Setup(m => m.Count()).Returns(2);। जब इस परीक्षण चल रहा है मैं त्रुटि निम्न मिल:

System.NotSupportedException : Expression references a method that does not belong to the mocked object: m => m.Count<User>()

मुझे लगता है कि यह एक स्थिर विधि जा रहा है .Count() की वजह से है, तो यह Moq द्वारा मज़ाक उड़ाया नहीं किया जा सकता। क्या एमओक का उपयोग करके इस सरल कार्रवाई का परीक्षण करने का कोई तरीका है और पूर्ण रूप से भंडारित पैटर्न का उपयोग नहीं कर रहा है, जैसा कि मुझे समझ में आता है कि किसी भी तरीके से यह .Count() भाग को टेस्ट करने योग्य होने के लिए हार्डकोड किया गया हो सकता है ... शायद मैं सिर्फ गलत तरीके से मैक्स का उपयोग करता हूं ? क्योंकि मुझे लगता है कि यह ईएफ कोड पहले के साथ काफी सरल और संभव होना चाहिए।

उत्तर

14

आप परीक्षण संस्थाओं मजाक रहे हैं, तो आप (हालांकि, मैं तो कुछ फेरबदल की आवश्यकता हो सकती एक IDE में नहीं हूँ) श्रृंखला

कुछ इस तरह करना चाहिए नीचे किसी भी आगे की नकली की जरूरत नहीं है

अद्यतन नई InMemoryDbSet

[Test] 
public void ModelValueShouldBeTwo() 
{ 
    //Build test users 
    var mockUsers = new InMemoryDbSet<User>(){ new User(), new User()}; 
    var mockDB = new Mock<ITestEntities>(); 
    //Set up mock entities to returntest users. 
    mockDB.Setup(db => db.Users).Returns(mockUsers); 

    var controller = new HomeController((ITestEntities)mockDB); 

    var view = controller.Index(); 

    Assert.IsInstanceOf<ViewResult>(view); 
    Assert.AreEqual(((ViewResult)view).Model, 2); 
} 

इस विस्तार के तरीकों मतलब बस परीक्षण डाटा आप की आपूर्ति की है के बंद काम करेंगे होगा शामिल करने के लिए।

http://geekswithblogs.net/Aligned/archive/2012/12/12/mocking-or-faking-dbset.aspx

+0

नोट: यह Async प्रश्नों के लिए काम नहीं करता है। इसके लिए समाधान के लिए आधिकारिक ईएफ दस्तावेज़ देखें: http://msdn.microsoft.com/en-us/data/dn314429.aspx#async –

1

नकली Count()

Count() के बजाय GetEnumerator() dbset मजाक पर एक अच्छा लेख के लिए नीचे देखें ऑब्जेक्ट IEnumerable<T> लागू पर एक विस्तार विधि है, और IDbSet<T> लागू करता IEnumerable<T>

एक्सटेंशन विधियों को उस वस्तु को पारित किया जाता है जिसे उन्हें बुलाया जाता है। इस मामले में हस्ताक्षर है:

public static int Count<TSource>(
    this IEnumerable<TSource> source, //This is your IDbSet that you are mocking 
    Func<TSource, bool> predicate 
) 

बजाय सेटअप Count() की कोशिश कर रहा एक विशिष्ट मूल्य वापस जाने के लिए, आप सेटअप IEnumerable<T> के सदस्यों को एक ही परिणाम प्राप्त कर सकते हैं। IEnumerable<T> के मामले में आपको केवल GetEnumerator() सेट करने के लिए Enumerator<T> सेट करना है जो दो मानों से अधिक है।

इस स्थिति में मैं आमतौर पर बनाने कि Enumerator<T> आइटम के एक जोड़े के साथ एक नई सूची बनाने और उस पर GetEnumerator() फोन करके:

mockUsers.Setup(m => m.GetEnumerator()).Returns(new List<Users> { 
    new User(), 
    new User() 
}.GetEnumerator()); 

अब, बेशक यह प्रभावी रूप से विस्तार विधि Count() अलावा करने के लिए परीक्षण जो कुछ भी आप अपने परीक्षण के साथ प्राप्त करने की कोशिश कर रहे हैं, जबकि यह एक बहुत ही कम जोखिम है जब एक्सटेंशन विधि .NET का एक हिस्सा है, तो यह ध्यान में रखना कुछ है कि आप अपने स्वयं के विस्तार विधियों का उपयोग और लेखन कर रहे हैं।

+1

यह 'आईडीबीसेट 'के विरुद्ध कुछ प्रकार के प्रश्नों के लिए काम करता है, लेकिन सभी नहीं उन्हें, उदाहरण के लिए 'FirstOrDefault()' जो अजीब अजीब रूप से उपयोग नहीं करता है। –

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