Moq का उपयोग करना और Callback
देखना लेकिन मैं इसे कैसे उपयोग करना है, यह समझने के लिए एक सरल उदाहरण नहीं पा सका हूं।
क्या आपके पास एक छोटा सा काम करने वाला स्निपेट है जो स्पष्ट रूप से समझाता है कि इसका उपयोग कैसे और कब करना है?
जवाबों:
Https://github.com/Moq/moq4/wiki/Quickstart को हराना मुश्किल
अगर यह पर्याप्त स्पष्ट नहीं है, तो मुझे लगता है कि एक डॉक्टर बग ...
संपादित करें: आपके स्पष्टीकरण के जवाब में ...
Setup
आपके द्वारा निष्पादित प्रत्येक नकली विधि के लिए, आपको चीजों को इंगित करना होगा:
.Callback
तंत्र कहते हैं, "मैं अभी वर्णन नहीं कर सकते, लेकिन जब एक कॉल इस तरह के आकार का होता है, मुझे वापस कॉल और मैं क्या किया जाना चाहिए करूँगा"। उसी धाराप्रवाह कॉल श्रृंखला के हिस्से के रूप में, आपको .Returns
" (यदि कोई हो) " के माध्यम से लौटने के लिए परिणाम नियंत्रित करने के लिए मिलता है । क्यूएस उदाहरणों में, एक उदाहरण यह है कि वे हर बार लौटाए जा रहे मूल्य को बढ़ाते हैं।
सामान्य तौर पर, आपको बहुत बार इस तरह के एक तंत्र की आवश्यकता नहीं होगी (xUnit टेस्ट पैटर्न में ilk Conditional Logic टेस्ट में एंटीपैटर्न के लिए शर्तें हैं), और यदि कोई भी सरल या अंतर्निहित तरीका है जिसे आपको स्थापित करने की आवश्यकता है, तो यह होना चाहिए वरीयता में इस्तेमाल किया।
जस्टिन एथरेज की Moq श्रृंखला में 4 का भाग 3 इसे कवर करता है, और यहां कॉलबैक का एक और उदाहरण है
कॉलबैक का एक सरल उदाहरण Moq पोस्ट के साथ कॉलबैक का उपयोग करके पाया जा सकता है ।
Callback
का रिटर्न वैल्यू से कोई लेना-देना नहीं है (जब तक कि आप इसे कोड के माध्यम से लिंक नहीं करते)। मूल रूप से यह केवल यह सुनिश्चित करता है कि कॉलबैक प्रत्येक आह्वान से पहले या बाद में कहा जाता है (इस पर निर्भर करता है कि आपने इसे पहले या बाद में जंजीर दिया Returns
है), सादा और सरल।
डेटा सेवा में भेजी गई इकाई का परीक्षण करने के लिए कॉलबैक का उपयोग करने का एक उदाहरण यहां एक प्रविष्टि को संभालता है।
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");
It.Is<T>
एक में Mock.Verify
अस्थायी कर्मियों के साथ परीक्षण कचरा के बजाय। लेकिन +1 क्योंकि मैं शर्त लगाता हूं कि बहुत सारे लोग हैं जो एक उदाहरण से सबसे अच्छा काम करेंगे।
Callback
Moq में दो प्रकार होते हैं । कॉल रिटर्न से पहले एक होता है; कॉल वापस आने के बाद दूसरा होता है।
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}");
});
दोनों कॉलबैक में, हम कर सकते हैं:
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 देखें ।
यहाँ अन्य अच्छे उत्तरों के शीर्ष पर, मैंने इसका उपयोग अपवाद फेंकने से पहले तर्क करने के लिए किया है। उदाहरण के लिए, मुझे उन सभी वस्तुओं को संग्रहीत करने की आवश्यकता थी, जिन्हें बाद में सत्यापन के लिए एक विधि में पारित किया गया था, और उस विधि (कुछ परीक्षण मामलों में) को एक अपवाद फेंकने की आवश्यकता थी। कॉलिंग एक्शन .Throws(...)
को Mock.Setup(...)
ओवरराइड करता Callback()
है और इसे कभी कॉल नहीं करता है। हालांकि, कॉलबैक के भीतर एक अपवाद को फेंककर, आप अभी भी सभी अच्छे सामान कर सकते हैं जो कॉलबैक को पेश करना है, और अभी भी एक अपवाद को फेंकना है।