Moq

2009-09-15 12 views
21

का उपयोग करके ईवेंट पंजीकरण की पुष्टि करना मैं एमवीपी पैटर्न using this example को लागू करने की कोशिश कर रहा एक एएसपीनेट (क्लासिक) अनुप्रयोग विकसित कर रहा हूं। इकाई के लिए मेरे प्रस्तोता परीक्षण की कोशिश कर रहा है और निम्न पद्धति का उपयोग कर में, psuedocode जिसके लिए इतनाMoq

//base view interface 
public interface IView 
{ 
    event EventHandler Init; 

    event EventHandler Load; 

    bool IsPostBack { get; } 

    void DataBind(); 

    bool IsValid { get;} 
} 

//presenter psuedo code 
public class SomePresenter 
{ 
    public SomePresenter(ISomeDomainService service, IView someView) 
    { 
      ... 
      //HOW DO WE TEST/VERIFY THAT THIS REGISTRATION OCCURS? 
      someView.Init += OnInit; 
      someView.Load += OnLoad; 
    } 
} 
... 
//consuming code that exercises the above code, that needs to be tested 
var presenter = new SomePresenter(someDomainService, someView); 

तरह लग रहा है मैं कैसे सत्यापित है कि प्रस्तोता कर रहा है क्या उम्मीद है अर्थात Init और लोड की घटनाओं के लिए पंजीकरण? यह आसानी से Phil Haack's example का उपयोग कर राइनो का मजाक उड़ाता है में किया जाता है ...

[Test] 
public void VerifyAttachesToViewEvents() 
{ 
    viewMock.Load += null; 
    LastCall.IgnoreArguments(); 
    viewMock.PostSaved += null; 
    LastCall.IgnoreArguments(); 
    mocks.ReplayAll(); 
    new PostEditController(viewMock, 
     this.dataServiceMock); 
    mocks.VerifyAll(); 
} 

... हम कैसे कर सकते हैं इस MOQ का उपयोग करते समय?

+1

+1 - मेरे सिर मारा एक ही दीवार के खिलाफ। – Gishu

उत्तर

14

ऐसा लगता है कि यह कार्यक्षमता moq में not currently available है, लेकिन भविष्य के संस्करण में दिखाई दे सकती है (मुझे 4.0.812.4 बीटा में एक नज़र था, लेकिन ऐसा लगता है)।

प्रश्न पूछने के लायक हो सकता है, "SomePresenter को व्यू के Load और Init ईवेंट की सदस्यता लेने की आवश्यकता क्यों है?" संभवतः ऐसा इसलिए है क्योंकि SomePresenter कक्षा को उन घटनाओं का जवाब देने की आवश्यकता है। इसलिए और Init ईवेंट को बढ़ाने के लिए Raise10 पर Raise विधि का उपयोग करना बेहतर हो सकता है, और उसके बाद SomePresenter ने उनके जवाब में सही काम किया।

+1

मैंने इसके बारे में सोचा, अनिवार्य रूप से कोड के इस टुकड़े का परीक्षण करने के लिए दो भाग हैं। 1. इंटरैक्शन परीक्षण ... जो घटना पंजीकरण 2. सत्यापित करता है राज्य आधारित परीक्षण ... जो सत्यापित करता है कि प्रस्तुतकर्ता में ईवेंट हैंडलर अपेक्षित व्यवहार करता है। स्वच्छ इकाई परीक्षण अलग-अलग मामलों में से प्रत्येक का परीक्षण करना होगा। के लिए एक समाधान (1) IVIEW इंटरफ़ेस सार्वजनिक इंटरफ़ेस IVIEW { ... सार्वजनिक शून्य RegisterForInit (eventhandler कॉलबैक) करने के तरीकों की एक जोड़ी जोड़ने के लिए है, ... } और सार्वजनिक SomePresenter (...) { ... someView.RegisterFoInit (OnInit) के प्रस्तोता निर्माता को संशोधित; } –

+0

और यह इस प्रकार है कि यदि आप ईवेंट सदस्यता शामिल हैं तो आप MOQ से सख्त मोक्स का उपयोग नहीं कर सकते हैं। (groan) – Gishu

+0

इस चिंता के बारे में गिटहब मुद्दे https://github.com/Moq/moq4/issues/49 के लिए अद्यतन लिंक। – KevM

0

मैं इस सवाल और समाधान जो मैं अपने प्रोजेक्ट में उपयोग कर रहा हूँ के साथ कुछ समय बिताया है:

यूनिट टेस्ट:

// Arrange 
TestedObject.Setup(x => x.OnEvent1()); 
TestedObject.Setup(x => x.OnEvent2()); 

// Act 
TestedObject.Object.SubscribeEvents(); 
TestedObject.Raise(x => x.Event1 += null); 
TestedObject.Raise(x => x.Event2 += null); 

// Assert 
TestedObject.Verify(x => x.OnEvent1(), Times.Once()); 
TestedObject.Verify(x => x.OnEvent2(), Times.Once()); 

परीक्षण विधि:

this.Event1 += OnEvent1; 
this.Event2 += OnEvent2; 

तो, सबसे पहले आपको उन तरीकों का नकल करना होगा जिन्हें आप घटनाओं को आवंटित करेंगे, जब आप मुझे कॉल करेंगे जो आप परीक्षण करना चाहते हैं, और आखिरकार सभी सब्स्क्राइब किए गए कार्यक्रमों को बढ़ाएं। यदि ईवेंट वास्तव में सब्सक्राइब किया गया है, तो निर्दिष्ट विधि को कॉल करने पर आप मोक से जांच सकते हैं।

जीएलएचएफ!

+4

हालांकि यह भ्रमित है। OnEvent1() विधि परीक्षण के तहत वस्तु पर है, जबकि मजाकिया वस्तु पर Raise() को कॉल करने की आवश्यकता है। क्या आप दिखाए गए सभी वर्गों के साथ वास्तविक कार्य कोड पोस्ट कर सकते हैं? –

0

मुझे पता है कि यह # डिलिप के लिए बहुत देर हो चुकी है, लेकिन यह उत्तर उन लोगों के लिए सहायक हो सकता है जो ऐसा करने की कोशिश कर रहे हैं। यहाँ परीक्षण वर्ग

public delegate void SubscriptionHandler<T>(string name, T handler); 

public class SomePresenterTest 
{ 
    [Test] 
    public void Subscription_Test() 
    { 
     var someServiceMock = new Mock<ISomeDomainService>(); 
     var viewMock = new Mock<IView>(); 
     //Setup your viewMock here 

     var someView = new FakeView(viewMock.Object); 
     EventHandler initHandler = null;    
     someView.Subscription += (n, h) => { if ((nameof(someView.Init)).Equals(n)) initHandler=h; }; 

     Assert.IsNull(initHandler); 

     var presenter = new SomePresenter(someServiceMock.Object, someView); 

     Assert.IsNotNull(initHandler); 
     Assert.AreEqual("OnInit", initHandler.Method?.Name); 
    } 
} 

FakeView एक डेकोरेटर पालन लागू किया है (घटनाक्रम पर ध्यान देना: Init/लोड {जोड़ने; हटाने}):

public class FakeView : IView 
{ 
    public event SubscriptionHandler<EventHandler> Subscription; 
    public event SubscriptionHandler<EventHandler> Unsubscription; 
    private IView _view; 
    public FakeView(IView view) 
    { 
     Assert.IsNotNull(view); 
     _view = view; 
    } 

    public bool IsPostBack => _view.IsPostBack; 
    public bool IsValid => _view.IsValid; 

    public event EventHandler Init 
    { 
     add 
     { 
      Subscription?.Invoke(nameof(Init), value); 
      _view.Init += value; 
     } 

     remove 
     { 
      Unsubscription?.Invoke(nameof(Init), value); 
      _view.Init -= value; 
     } 
    } 
    public event EventHandler Load 
    { 

     add 
     { 
      Subscription?.Invoke(nameof(Load), value); 
      _view.Init += value; 
     } 

     remove 
     { 
      Unsubscription?.Invoke(nameof(Load), value); 
      _view.Init -= value; 
     } 
    } 

    public void DataBind() 
    { 
     _view.DataBind(); 
    } 
}