2010-10-11 12 views
6

का उपयोग कर एक आवेदन में परीक्षण Bus.Send मैं NServiceBus का उपयोग कर मेरे ऐप .NET अनुप्रयोग में इस कोड है:NServiceBus

Bus.Send<IServiceStarted>(e => 
          { 
            e.ServiceInfo = ReadServiceInfo(); 
            e.EventTime = DateProvider.Now; 
          }); 

आप इकाई परीक्षण इस तरह के एक कोड के बारे में कैसे जाना होगा?

+0

क्या आप 'Bus.Send', या कोड भेजने वाले कोड के बारे में पूछ रहे हैं? – arootbeer

+0

arootbeer, मैं संदेश भेजने वाले कोड के बारे में पूछ रहा हूं। मैं जिस सटीक कोड का परीक्षण करना चाहता हूं वह ऊपर दिए गए प्रश्न में दिया गया है। – mgamer

+0

मैंने रुचि रखने वाले मामले में प्रतिनिधि कोड को स्थानांतरित करने के संबंध में एक संपादन जोड़ा। – arootbeer

उत्तर

3

जब तक आपके Bus चर के रूप में एक IBus उदाहरण है, तो आप बस वर्ग है कि इस विधि में शामिल करने के लिए एक मज़ाक उड़ाया IBus कार्यान्वयन प्रदान कर सकते हैं, और (, उचित प्रतिनिधि के साथ अगर आप ऐसा चाहते हैं) सत्यापित करें कि संदेश उस पर बुलाया गया था परीक्षण के लिए विधि लागू करने के बाद। इसके अलावा, आप Bus.Send स्वयं परीक्षण कर रहे हैं, जो ऐसा कुछ नहीं है जो आपको करना चाहिए।

public class ClassThatSendsMessages 
{ 
    private readonly IBus _bus; 
    public ClassThatSendsMessages(IBus bus /*, ... */) 
    { 
     _bus = bus; 
     /* ... */ 
    } 

    public void CodeThatSendsMessage() 
    { 
     /* ... */ 
     _bus.Send<IMyMessage>(mm => mm.Property1 = "123"); 
     /* ... */ 
    } 
} 

public class ClassThatTestsClassThatSendsMessages 
{ 
    public void CallCodeThatSendsMessage() 
    { 
     //Mock IBus object here 
     var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */) 

     objectToTest.CodeThatSendsMessage(); 

     //Verify that IBus mock's Send() method was called 
    } 
} 

वहाँ प्रतिनिधि के तर्क का परीक्षण दृष्टिकोण दो तरीके हैं: आप, बशर्ते अभिव्यक्ति पेड़ को तोड़ने की कोशिश कर सकते हैं या आप एक नामित विधि करने के लिए इसे बदल सकते हैं और इसे उस तरह से पारित कर सकते हैं। मैं भाव में गहरी मिल गया कभी नहीं किया है, तो मैं बाद का एक उदाहरण प्रदान करेंगे:

public static class MyMessageBuilder 
{ 
    public static void Build(IMyMessage message) { /* ... */ } 
} 

public class ClassThatTestsMyMessageBuilder 
{ 
    public void CallCodeThatBuildsMessage() 
    { 
     var message = Test.CreateInstance<IMyMessage>(MyMessageBuilder.Build); 

     //Verify message contents 
    } 
} 

उपयोग:

public class ClassThatSendsMessages 
{ 
    private readonly IBus _bus; 
    public static Action<IMyMessage> BuildMessage { private get; set; } 
    public ClassThatSendsMessages(IBus bus /*, ... */) 
    { 
     _bus = bus; 
     /* ... */ 
    } 

    public void CodeThatSendsMessage() 
    { 
     /* ... */ 
     _bus.Send<IMyMessage>(mm => BuildMessage (mm)); 
     /* ... */ 
    } 
} 

मैं एक कंटेनर है कि करने के लिए प्रतिनिधि इंजेक्शन कर सकते हैं के बारे में पता नहीं कर रहा हूँ रचनाकार, लेकिन फिर मैंने बहुत मुश्किल नहीं देखा है, ताकि प्रतिनिधि को स्थापित करने का एक बेहतर तरीका हो।

संपादित

मैं हाल ही में मेरे अपने परीक्षण में इस मुद्दे में चलाने की है, और मैं वास्तव में अपने स्वयं के निर्माता में विधि बाहर निकलने के लिए होने की तरह नहीं है। इसलिए मैंने यह पता लगाने के लिए तैयार किया कि क्या मैं "जगह में" प्रतिनिधि का परीक्षण कर सकता हूं। यह पता चला है कि आप कर सकते हैं:

public class ClassThatTestsClassThatSendsMessages 
{ 
    public void CallCodeThatSendsMessage() 
    { 
    Action<IMyMessage> messageAction = null; 

    //Mock IBus object here 
    mockedIBus.Setup(b => b.Send(Args.IsAny<Action<IMyMessage>>())) 
     .Callback((Action<IMyMessage> a) => messageAction = a); 
    var myMessage = Test.CreateInstance<IMyMessage>(); 

    var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */) 

    //Run the code that sends the message 
    objectToTest.CodeThatSendsMessage(); 
    //Run the code that populates the message 
    messageAction(myMessage); 

    //Verify expectations on Setups 
    //Verify the message contents; 
    } 
} 

वहाँ समझौतों से यहाँ हैं - निश्चित रूप से एक इनलाइन प्रतिनिधि के रूप में इसे छोड़ने से SRP के साथ और अधिक आज्ञाकारी संदेश बिल्डर एक इंटरफ़ेस में बाहर खींच रहा है (परीक्षण के रूप में स्पष्ट रूप से दर्शाता है: क्या आप करने के लिए है सभी कोड का परीक्षण करने के लिए दो बार कार्य करें)। हालांकि, यह कोड आकार और पठनीयता दोनों में लाभ प्रस्तुत करता है।

इसके अतिरिक्त, यह कोड Moq-specific है; मुझे नहीं पता कि प्रतिनिधि को राइनोमोक्स मॉक से वापस लेना संभव है या उसके लिए सिंटैक्स क्या होगा।

+1

यदि कोड का परीक्षण एक संदेश हैंडलर है, तो आप NServiceBus.Testing लाइब्रेरी का उपयोग कर सकते हैं जो आपके लिए बस का मज़ाक उड़ा सकता है, और यदि आप आईबीस संपत्ति के लिए सेटर इंजेक्शन का उपयोग करते हैं, तो यह आपके हैंडलर में भी इंजेक्ट करेगा। –

+0

arootbeer, मेरे लिए कठिन हिस्सा यह सत्यापित करना है कि उचित विधि के साथ भेजें विधि को कॉल किया गया था? राइनो मोक्स एक विधि प्रदान करता है AssertWasCalled जो तर्कों पर बाधाओं को स्वीकार करता है, लेकिन क्या यह एक बाधा है कि आपको यह सत्यापित करने की अनुमति मिलती है कि उचित प्रतिनिधि के साथ विधि कहलाती है या नहीं? – mgamer

+0

आप प्रतिनिधि को खींचने और उसकी संपत्तियों का निरीक्षण करने के लिए GetArgumentsForCallsMadeOn का उपयोग करने का प्रयास कर सकते हैं: http://kashfarooq.wordpress.com/2009/01/10/rhino-mocks-and-getargumentsforcallsmadeon/ – PatrickSteele

2

एनएसबी के साथ आने वाले परीक्षण ढांचे की जांच करें, यह नीचे राइनो का उपयोग कर रहा है: http://nservicebus.com/UnitTesting.aspx। डाउनलोड में कई नमूने हैं जो इसे एनयूनीट के साथ उपयोग करते हैं। आप इसे एमएसटीएस्ट के तहत भी काम करने के लिए प्राप्त कर सकते हैं।

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

  • कोई संबंधित समस्या नहीं^_^