2010-01-14 6 views
5

तक पहुंचने के लिए मैंने अभी तक एक पहले से स्थापित प्रोजेक्ट पर यूनिट परीक्षण (xUnit और Moq का उपयोग करके) लागू करना शुरू कर दिया है। परियोजना एकता कंटेनर के माध्यम से बड़े पैमाने पर निर्भरता इंजेक्शन का उपयोग करती है।Moq और पैरामीटर

मेरे पास दो सेवाएं हैं ए और बी सेवा ए इस मामले में परीक्षण किया जा रहा है। सेवा ए कॉल बी और इसे एक आंतरिक समारोह में एक प्रतिनिधि प्रदान करता है। यह 'कॉलबैक' का उपयोग ए को सूचित करने के लिए किया जाता है जब एक संदेश प्राप्त हुआ है जिसे इसे संभालना चाहिए।

इसलिए

एक कॉल (जहां ख सेवा बी का एक उदाहरण है):

b.RegisterHandler(Guid id, Action<byte[]> messageHandler); 

आदेश में सेवा एक परीक्षण करने के लिए, मैं, messageHandler कॉल करने के लिए सक्षम होना चाहिए के रूप में इस एक ही तरीका है कि वर्तमान में यह स्वीकार करता है संदेश।

क्या यह मोक का उपयोग करके किया जा सकता है? अर्थात। क्या मैं सेवा बी का नकल कर सकता हूं, जैसे कि RegisterHandler कहा जाता है, messageHandler का मान मेरे परीक्षण में पारित किया गया है?

या मुझे इसे फिर से डिजाइन करने की आवश्यकता है? क्या इस मामले में मुझे कोई डिज़ाइन पैटर्न उपयोग करना चाहिए? क्या किसी को इस तरह के डिजाइन पर किसी भी अच्छे संसाधन के बारे में पता है?

उत्तर

9

आप कॉलबैक मॉक पर विधि (नाम समानता आकस्मिक है) का उपयोग करके कॉलबैक का एक उदाहरण (या किसी अन्य इनपुट पैरामीटर) प्राप्त कर सकते हैं :

[TestMethod] 
public void Test19() 
{ 
    Action<byte[]> callback = null; 

    var bSpy = new Mock<IServiceB>(); 
    bSpy.Setup(b => b.RegisterHandler(It.IsAny<Guid>(), It.IsAny<Action<byte[]>>())) 
     .Callback((Guid g, Action<byte[]> a) => callback = a); 

    var sut = new ServiceA(bSpy.Object); 
    sut.RegisterCallback(); 

    Assert.AreEqual(sut.Do, callback); 
} 

यह काम करता है जब serviceà इस रूप में परिभाषित किया गया है:

public class ServiceA 
{ 
    private readonly IServiceB b; 

    public ServiceA(IServiceB b) 
    { 
     if (b == null) 
     { 
      throw new ArgumentNullException("b"); 
     } 

     this.b = b; 
    } 

    public void RegisterCallback() 
    { 
     this.b.RegisterHandler(Guid.NewGuid(), this.Do); 
    } 

    public void Do(byte[] bytes) 
    { 
    } 
} 
0

हां आप अपेक्षित और अप्रत्याशित परिचालनों का जवाब देने के लिए Moq ऑब्जेक्ट सेट कर सकते हैं। यहाँ एक दृश्य स्टूडियो यूनिट टेस्ट उदाहरण है ...

[TestMethod] 
public void MyTest() 
    { 
     var moqObject = new Mock<ServiceB>(); 

     // Setup the mock object to throw an exception if a certain value is passed to it... 
     moqObject.Setup(b => b.RegisterHandle(unexpectedValue).Throws(new ArgumentException()); 

     // Or, setup the mock object to expect a certain method call... 
     moqObject.Setup(b => b.RegisterHandle(expectedValue)); 

     var serviceA = new ServiceA(moqObject.Object); 

     serviceA.DoSomethingToTest(); 

     // This will throw an exception if an expected operation didn't happen... 
     moqObject.VerifyAll(); 
    }