क्या आप मुझे Moq Callback को समझने में मदद कर सकते हैं?


96

Moq का उपयोग करना और Callbackदेखना लेकिन मैं इसे कैसे उपयोग करना है, यह समझने के लिए एक सरल उदाहरण नहीं पा सका हूं।

क्या आपके पास एक छोटा सा काम करने वाला स्निपेट है जो स्पष्ट रूप से समझाता है कि इसका उपयोग कैसे और कब करना है?

जवाबों:


83

Https://github.com/Moq/moq4/wiki/Quickstart को हराना मुश्किल

अगर यह पर्याप्त स्पष्ट नहीं है, तो मुझे लगता है कि एक डॉक्टर बग ...

संपादित करें: आपके स्पष्टीकरण के जवाब में ...

Setupआपके द्वारा निष्पादित प्रत्येक नकली विधि के लिए, आपको चीजों को इंगित करना होगा:

  • आदानों पर अड़चन
  • उस मान के लिए / जिस तरीके से रिटर्न वैल्यू (यदि कोई है) प्राप्त किया जाना है

.Callbackतंत्र कहते हैं, "मैं अभी वर्णन नहीं कर सकते, लेकिन जब एक कॉल इस तरह के आकार का होता है, मुझे वापस कॉल और मैं क्या किया जाना चाहिए करूँगा"। उसी धाराप्रवाह कॉल श्रृंखला के हिस्से के रूप में, आपको .Returns" (यदि कोई हो) " के माध्यम से लौटने के लिए परिणाम नियंत्रित करने के लिए मिलता है । क्यूएस उदाहरणों में, एक उदाहरण यह है कि वे हर बार लौटाए जा रहे मूल्य को बढ़ाते हैं।

सामान्य तौर पर, आपको बहुत बार इस तरह के एक तंत्र की आवश्यकता नहीं होगी (xUnit टेस्ट पैटर्न में ilk Conditional Logic टेस्ट में एंटीपैटर्न के लिए शर्तें हैं), और यदि कोई भी सरल या अंतर्निहित तरीका है जिसे आपको स्थापित करने की आवश्यकता है, तो यह होना चाहिए वरीयता में इस्तेमाल किया।

जस्टिन एथरेज की Moq श्रृंखला में 4 का भाग 3 इसे कवर करता है, और यहां कॉलबैक का एक और उदाहरण है

कॉलबैक का एक सरल उदाहरण Moq पोस्ट के साथ कॉलबैक का उपयोग करके पाया जा सकता है ।


3
हाय रूबेन मैं Moq सीख रहा हूं और यदि आप चाहें तो मुझे यह समझने के लिए बहुत सारे उदाहरणों को उभारा जा रहा है कि इसका उपयोग कैसे करना है। मेरी समस्या यह है कि मुझे समझ नहीं आ रहा है कि इसे कब इस्तेमाल किया जाए। क्या मुझे समझ में आया कि समस्या हल हो गई है मैं अपना कोड लिखूंगा। यदि आप इसे अपने शब्दों में समझाते तो आप कब कॉलबैक का उपयोग करते? धन्यवाद आपके समय की सराहना करते हैं
user9969

15
[कड़ी] को हराना मुश्किल? हर्गिज नहीं। यह लिंक आपको दर्जनों अलग-अलग चीजों को करने का तरीका दिखाता है , लेकिन आपको यह नहीं बताता कि आपको उनमें से कोई भी करने की आवश्यकता क्यों है। जो प्रलेखन के लिए एक आम समस्या है, मैंने पाया है। मैं शून्य उंगलियों पर भरोसा कर सकता हूं कि टीडीडी + की अच्छी, स्पष्ट व्याख्याओं की संख्या जो मुझे मिली है। अधिकांश ज्ञान का एक स्तर मान लेते हैं, जो अगर मेरे पास होता, तो मुझे लेख पढ़ने की आवश्यकता नहीं होती।
रयान लुंडी

@Kyralessa: मैं आपकी बात लेता हूं। मैं व्यक्तिगत रूप से बहुत किताबी ज्ञान प्राप्त कर रहा था ताकि जल्दी से सामान को पूरी तरह से सही पाया। दुर्भाग्य से मैं एक बेहतर उदाहरण के बारे में नहीं जानता हूँ कि जिन्हें मैंने पोस्ट के अंत में जोड़ा था। क्या आपको एक ढूंढना चाहिए, इसे यहां पोस्ट करें और मुझे इसे संपादित करने में खुशी होगी (या DIY के लिए स्वतंत्र महसूस)
रूबेन बार्टेलिंक

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

1
@OhadSchneider मेरे लिंक का अनुसरण करें ... आप सही हैं! फ़्लुएंट इंटरफ़ेस बदल गया है, लेकिन आश्चर्य (लेकिन वास्तव में पर्याप्त रुचि नहीं है क्योंकि Moq का उपयोग नहीं किया है) अगर फ्लुएंट इंटरफ़ेस बदल गया है (तो संभावना नहीं है, यानी मैंने एक गलत धारणा बना ली है और मैंने जिस चीज़ से जुड़ा हुआ है उसे पढ़ा है क्योंकि मैं सामान्य रूप से इसे बाहर काम करूँगा। स्वतः पूर्णता से)। आशा है कि फिक्स आपकी बात को संबोधित करेगा, मुझे बताएं कि क्या यह नहीं है
रूबेन बार्टलिंक

60

डेटा सेवा में भेजी गई इकाई का परीक्षण करने के लिए कॉलबैक का उपयोग करने का एक उदाहरण यहां एक प्रविष्टि को संभालता है।

var mock = new Mock<IDataService>();
DataEntity insertedEntity = null;

mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1) 
           .Callback((DataEntity de) => insertedEntity = de);

वैकल्पिक सामान्य विधि वाक्यविन्यास:

mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1) 
           .Callback<DataEntity>(de => insertedEntity = de);

तब आप कुछ इस तरह का परीक्षण कर सकते हैं

Assert.AreEqual("test", insertedEntity.Description, "Wrong Description");

4
यकीनन कि विशेष मामले (आप राज्य या व्यवहार के खिलाफ परीक्षण व्यक्त करने के लिए कोशिश कर रहे हैं, इस पर निर्भर करता है) के लिए, यह कुछ मामलों में क्लीनर एक का उपयोग करने के हो सकता है It.Is<T>एक में Mock.Verifyअस्थायी कर्मियों के साथ परीक्षण कचरा के बजाय। लेकिन +1 क्योंकि मैं शर्त लगाता हूं कि बहुत सारे लोग हैं जो एक उदाहरण से सबसे अच्छा काम करेंगे।
बजे रूबेन बार्टलिंक

10

CallbackMoq में दो प्रकार होते हैं । कॉल रिटर्न से पहले एक होता है; कॉल वापस आने के बाद दूसरा होता है।

var message = "";
mock.Setup(foo => foo.Execute(arg1: "ping", arg2: "pong"))
    .Callback((x, y) =>
    {
        message = "Rally on!";
        Console.WriteLine($"args before returns {x} {y}");
    })
    .Returns(message) // Rally on!
    .Callback((x, y) =>
    {
        message = "Rally over!";
        Console.WriteLine("arg after returns {x} {y}");
    });

दोनों कॉलबैक में, हम कर सकते हैं:

  1. विधि तर्कों का निरीक्षण करें
  2. विधि तर्क पर कब्जा
  3. संदर्भ की स्थिति बदलें

2
दरअसल, दोनों कॉल रिटर्न से पहले होते हैं (जहां तक ​​कॉलर का संबंध है)। देखें stackoverflow.com/a/28727099/67824
ओहद श्नाइडर

6

Callbackकिसी भी कस्टम कोड को निष्पादित करने का एक साधन है जिसे आप चाहते हैं कि जब कॉल मॉक के तरीकों में से एक के लिए किया जाता है। यहाँ एक सरल उदाहरण है:

public interface IFoo
{
    int Bar(bool b);
}

var mock = new Mock<IFoo>();

mock.Setup(mc => mc.Bar(It.IsAny<bool>()))
    .Callback<bool>(b => Console.WriteLine("Bar called with: " + b))
    .Returns(42);

var ret = mock.Object.Bar(true);
Console.WriteLine("Result: " + ret);

// output:
// Bar called with: True
// Result: 42

मैं हाल ही में इसके लिए एक दिलचस्प उपयोग के मामले में भाग गया। माना कि आप अपने मॉक से कुछ कॉल की उम्मीद करते हैं, लेकिन वे समवर्ती रूप से होते हैं। इसलिए आपके पास उस आदेश को जानने का कोई तरीका नहीं है जिसमें वे कॉल करेंगे, लेकिन आप जानना चाहते हैं कि आपके द्वारा अपेक्षित कॉल (आदेश के बावजूद) किया गया था। आप ऐसा कुछ कर सकते हैं:

var cq = new ConcurrentQueue<bool>();
mock.Setup(f => f.Bar(It.IsAny<bool>())).Callback<bool>(cq.Enqueue);
Parallel.Invoke(() => mock.Object.Bar(true), () => mock.Object.Bar(false));
Console.WriteLine("Invocations: " + String.Join(", ", cq));

// output:
// Invocations: True, False

BTW भ्रामक "पहले Returns" और Returns"भेद " के बाद भ्रमित नहीं होता है। यह केवल एक तकनीकी अंतर है कि आपका कस्टम कोड Returnsमूल्यांकन के बाद चलेगा या पहले। कॉलर की आँखों में, मान वापस आने से पहले दोनों चलेंगे। वास्तव में, यदि विधि void-पूर्ण है तो आप कॉल भी नहीं कर सकते हैं Returnsऔर फिर भी यह उसी तरह काम करता है। अधिक जानकारी के लिए https://stackoverflow.com/a/28727099/67824 देखें


1

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.