मैं अपने तरीके से स्पष्ट रूप से निर्दिष्ट या एक अधिभार का उपयोग किए बिना अपने हस्ताक्षर में एक वैकल्पिक तर्क देने वाली विधि Moq कैसे करूं?


119

निम्नलिखित इंटरफ़ेस को देखते हुए:

public interface IFoo
{
    bool Foo(string a, bool b = false);
}

Moq का उपयोग करके इसे नकली करने का प्रयास किया जा रहा है:

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);

संकलन समय पर निम्नलिखित त्रुटि देता है:

एक अभिव्यक्ति ट्री में एक कॉल या आह्वान नहीं हो सकता है जो वैकल्पिक तर्कों का उपयोग करता है

मैंने ऊपर के मुद्दे को Moq के मुद्दों की सूची में वृद्धि के रूप में उठाया है और यह 4.5 रिलीज (जब भी है) को सौंपा गया प्रतीत होता है।

मेरा सवाल यह है: मुझे क्या करना चाहिए कि उपरोक्त जल्द ही कभी भी तय नहीं होगा? क्या मेरे विकल्प केवल या तो स्पष्ट रूप से वैकल्पिक पैरामीटर के डिफ़ॉल्ट मान को हर बार सेट करते हैं, जब भी मैं इसका मजाक उड़ाता हूं (जो पहली जगह में किसी को निर्दिष्ट करने की बात को पराजित करता है) या बूल के बिना एक अधिभार बनाने के लिए (जैसे मैंने क्या किया होगा) C # 4 से पहले)?

या किसी को इस मुद्दे को दूर करने के लिए एक और अधिक चतुर तरीका है?


5
क्या दूसरे पैरामीटर के लिए इसे इट.सैनी <bool> () निर्दिष्ट करना उचित होगा?
पॉल डी'अवेट

एक साल और आधे बाद में यह अभी भी सच है ..
मुकुस

@ मूकस, एक पीआर, भाई को छोड़ने के लिए स्वतंत्र महसूस करें।
IamDOM

जवाबों:


91

मेरा मानना ​​है कि अभी के लिए आपका एकमात्र विकल्प स्पष्ट रूप boolसे सेटअप में पैरामीटर को शामिल करना है Foo

मुझे नहीं लगता कि यह डिफ़ॉल्ट मान निर्दिष्ट करने के उद्देश्य को पराजित करता है। डिफ़ॉल्ट मूल्य कॉलिंग कोड के लिए एक सुविधा है, लेकिन मुझे लगता है कि आपको अपने परीक्षणों में स्पष्ट होना चाहिए। मान लें कि आप boolपैरामीटर निर्दिष्ट करना छोड़ सकते हैं । क्या होता है, अगर भविष्य में, कोई व्यक्ति का डिफ़ॉल्ट मान बदलता bहै true? इस में नाकाम रहने के परीक्षण (और हक तो) के लिए नेतृत्व करेंगे, लेकिन वे छिपा धारणा है कि की वजह से ठीक करने के लिए और अधिक कठिन हो जाएगा bहै false। स्पष्ट रूप से निर्दिष्ट boolपैरामीटर का एक और लाभ है: यह आपके परीक्षणों की पठनीयता में सुधार करता है। उनके माध्यम से जाने वाले किसी को जल्दी से पता चल जाएगा कि एक Fooकार्य है जो दो मापदंडों को स्वीकार करता है। यह मेरा 2 सेंट है, कम से कम :)

हर बार जब आप इसे मॉक करते हैं, तो इसे निर्दिष्ट करने के लिए, डुप्लिकेट कोड की नकल न करें: किसी फंक्शन में मॉक बनाएं और / या इनिशियलाइज़ करें, ताकि आपके पास केवल एक ही बदलाव हो। यदि आप वास्तव में चाहते हैं, तो आप Fooइस प्रारंभिक कार्य में डुप्लिकेट मापदंडों को दोहराकर Moq के स्पष्ट लघु-आगमन को दूर कर सकते हैं :

public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false)
{
    if(!b)
    {
        fooMock.Setup(mock => mock.Foo(a, b)).Returns(false);
    }
    else
    {
        ...
    }
}

1
उत्कृष्ट जवाब; मैं पहले से ही आगे बढ़ गया और इसे स्पष्ट रूप से मेरे मोक्स में निर्दिष्ट किया लेकिन आपका जवाब बहुत स्पष्ट और तार्किक तरीके से पुष्टि करता है कि मुझे इसे इस तरह से क्यों करना चाहिए। धन्यवाद, @ क्रिस।
अप्पुलस

9
एक डिफ़ॉल्ट पैरामीटर बदलना "परीक्षणों को तोड़ना" चाहिए। जब कोई डिफ़ॉल्ट बदल जाता है तो परीक्षण विफल नहीं होता है, यह खराब परीक्षण का संकेत हो सकता है। कोड चूक का उपयोग कर सकता है लेकिन परीक्षण नहीं करता है?
पॉप कैटलिन

थोड़ी देर हो गई, लेकिन मैंने Moq के साथ एक इंटरफेस (Dapper में IDConnection) को मॉक करने की कोशिश कर रहा है और मुझे अभी भी वही त्रुटि मिल रही है। कोई विचार क्यों? नमूना लाइन: mockDB.Setup (x => x.Query <MyObject> (It.IsAny <string>), It.IsAny <DynamicParameters> (), It.IsAny <IDRTransaction> (), false, 600))। रिटर्न (नई सूची <MyObject> ()); अंतिम दो मान मेरे द्वारा सेट की जा रही विधि पर वैकल्पिक पैरामीटर हैं।
रालेशक

4
Arrgggh! भयानक if (!x) {} else {}विरोधी पैटर्न :)
निकोडेमस 13

1
@ nicodemus13 हां, लेकिन मैं प्रश्न में ओपी के उदाहरण के करीब कोड उदाहरण रखने की कोशिश कर रहा था। मैं जरूरी इसकी वकालत नहीं करूंगा :)
क्रिस मेंटल

8

बस आज इस मुद्दे का सामना करना पड़ा, Moq इस उपयोग के मामले का समर्थन नहीं करता है। तो, ऐसा लगता है कि इस मामले के लिए विधि को ओवरराइड करना पर्याप्त होगा।

public interface IFoo
{
    bool Foo(string a);

    bool Foo(string a, bool b);
}

अब दोनों विधियाँ उपलब्ध हैं और यह उदाहरण काम करेगा:

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);

2

4.10.1 Moq संस्करण का उपयोग करके मैं निम्नलिखित कार्य करने में सक्षम हूं

इंटरफ़ेस के साथ:

public interface IFoo
{
    bool Foo(string a, bool b = false);
}

और मॉक

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>(), It.IsAny<bool>())).Returns(false);

पहले पैरामीटर के साथ फू को कॉल ठीक करता है

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