2013-06-11 3 views
23

पर मैं मोक का उपयोग कर रहा हूं और प्रीसेट उचित डिफ़ॉल्ट के साथ अपने मैक्स बनाने के लिए बिल्डर वर्ग बनाना चाहता हूं आवश्यकतानुसार परीक्षण सेटअप के दौरान ओवरराइड किया जाना चाहिए। मैंने जो दृष्टिकोण लिया वह विस्तार विधियों का उपयोग करता है जिसमें मैं इनपुट पैरामीटर मान और अपेक्षित आउटपुट पास करता हूं। ऐसा करने में, मुझे लगता है कि मुझे अर्थात् समकक्ष कोड होने के लिए अलग-अलग व्यवहार दिखाई दे रहे हैं: इसे पास कर रहा है। Isny ​​() सीधे एक सेटअप में बनाम बनाम बनाम बना रहा है। यह एक सेटअप में अप्रत्यक्ष रूप से है। उदाहरण:इसे पास करने के बीच क्या अंतर है। आईएसएनी <int>() और इसका मूल्य वैल्यू <int>() का एक विधि सेटअप

public interface IFoo 
{ 
    bool Bar(int value); 
    bool Bar2(int value); 
} 
public class Foo : IFoo 
{ 
    public bool Bar(int value) { return false; } 
    public bool Bar2(int value) { return false; } 
} 

var mock = new Mock<IFoo>(); 
mock.Setup(x => x.Bar(It.IsAny<int>())).Returns(true); 
Assert.IsTrue(mock.Object.Bar(123));     // Succeeds 

var myValue = It.IsAny<int>(); 
mock.Setup(x => x.Bar2(myValue)).Returns(true); 
Assert.IsTrue(mock.Object.Bar2(123));     // Fails 

दोनों कॉल समकक्ष (मेरे लिए) हैं, फिर भी बार 2 पर कॉल दावा विफल रहता है। ऐसा क्यों है?

उत्तर

33

It.IsAny केवल Setup निर्माण के भीतर उपयोग किए जाने पर विधि कॉल के भविष्य के इनवोकेशन से मेल खाने के लिए Moq को अनुमति देता है। जब Setup को मोक कहा जाता है तो पहले से सेट-अप विधि कॉल के कैश में विधि कॉल जोड़ता है। ध्यान दें कि आपके उदाहरण में Setup पर तर्क Expression<Func<IFoo, bool>> टाइप करें। चूंकि आप Expression में गुजर रहे हैं, वास्तविक विधि कॉल लागू नहीं किया गया है और मूक में अभिव्यक्ति को पार करने की क्षमता है कि यह पता लगाने के लिए कि विधि कॉल के कौन से पैरामीटर स्पष्ट थे, और It.IsAny तर्क हैं। यह यह निर्धारित करने की क्षमता का उपयोग करता है कि रनटाइम पर भविष्य की विधि कॉल पहले से सेट-अप विधि कॉल में से किसी एक से मेल खाती है या नहीं।

ताकि इसे बनाने के लिए इतना है कि विधि Bar तर्क It.IsAny<int>() स्वीकार कर सकते हैं के लिए, यह सुनिश्चित करने के लिए आवश्यक है It.IsAny<int>() वापसी एक int (के बाद से है कि Bar के पैरामीटर के प्रकार है)। आम तौर पर, It.IsAny<T> का रिटर्न प्रकार T होना चाहिए। T का मनमाना मूल्य चुना जाना चाहिए। सबसे प्राकृतिक विकल्प default(T) है, जो संदर्भ प्रकारों और मूल्य प्रकारों के लिए काम करता है। (डिफ़ॉल्ट कीवर्ड here) के बारे में और पढ़ें। आपके मामले में, यह default(int) है, जो 0 है।

तो जब आप वास्तव में It.IsAny<int>() का मूल्यांकन करते हैं तो 0 का मान तुरंत लौटा दिया जाता है। हालांकि, जब आप It.IsAny<int>()Expression (Setup विधि के तर्क में) के रूप में उपयोग करते हैं, तो विधि कॉल की वृक्ष संरचना संरक्षित होती है और Moq Expression द्वारा समेकित विधि कॉल में भावी विधि आमंत्रण से मेल खा सकता है।

इसलिए, भले ही आप It.IsAny<int>() किसी भी सार्थक तरीके में एक चर के रूप में नहीं रख सकते हैं, तो आप एक चर में पूरे Expression रख सकते हैं:

Expression<Func<IFoo, bool>> myExpr = x => x.Bar2(It.IsAny<int>()); 
mock.Setup(myExpr).Returns(true); 
Assert.IsTrue(mock.Object.Bar2(123)); 

अंत में, मैं बस तुम्हें याद दिलाना Moq खुला स्रोत है कि चाहते हैं। स्रोत here उपलब्ध है। मुझे यह स्रोत कोड रखने के लिए मूल्यवान लगता है ताकि मैं चारों ओर क्लिक कर सकूं और कोड और यूनिट परीक्षणों का पता लगा सकूं।

+1

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

+0

मेरे लिए उस जादूगर को साफ़ करने के लिए धन्यवाद! मैं कहने की कोशिश कर रहा था "var anyFooParam = It.IsAny (); var anyBarParam = It.IsAny ();" यह देखने के लिए कि क्या यह मेरे परीक्षणों को और अधिक पठनीय बना देगा: .Setup (mock => mock.method (anyFooParam, anyBarParam))। रिटर्न (कुछ!) –

1

It.IsAny<int>() लौट पूर्णांक के प्रकार तो अपने दूसरे सेटअप बराबर है करने के लिए है और 0 देता है,:

mock.Setup(x => x.Bar2(0)).Returns(true); 

मैं moq कोड की जाँच नहीं था, लेकिन मैं बहुत यकीन है कि जब यह अभिव्यक्ति का मूल्यांकन करता हूँ सेटअप विधि में, यह ध्यान में रखता है कि पैरामीटर वास्तव में यह है। यह एक सामान्य संख्या बनाम है।

यदि आप सीधे अपने सहायक तरीकों में सेटअप बनाते हैं, तो इसे बेहतर तरीके से बंद कर देते हैं, और इसे पास नहीं करते हैं।

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