2012-01-20 7 views
13

मैं अपने टाइमर मॉक को सौंपा गया ईवेंट हैंडलर आग लगाने की कोशिश कर रहा हूं। मैं यहां इस निजी विधि का परीक्षण कैसे कर सकता हूं?मैं एक मॉक को सौंपा गया ईवेंट हैंडलर कैसे चला सकता हूं?

public interface ITimer 
{ 
    void Start(); 
    double Interval { get; set; } 
    event ElapsedEventHandler Elapsed; 
} 

क्लाइंट क्लास इस ऑब्जेक्ट को इवेंट हैंडलर असाइन करता है। मैं इस वर्ग में तर्क का परीक्षण करना चाहता हूं।

_timer.Elapsed += ResetExpiredCounters; 

और सौंपा विधि निजी

private void ResetExpiredCounters(object sender, ElapsedEventArgs e) 
{ 
    // do something 
} 

है मैं अपने नकली में इस ईवेंट हैंडलर है और यह किसी भी तरह चलाना चाहते हैं। मैं यह कैसे कर सकता हूँ?

अद्यतन:

मुझे एहसास हुआ कि इससे पहले कि मैं ईवेंट हैंडलर सौंपा मैं घटना को ऊपर उठाने की गई थी। मुझे लगता है कि सही किया लेकिन मैं अभी भी यह त्रुटि प्राप्त:

मैं इसे इस तरह बढ़ा:

_timer.Raise(item => item.Elapsed += null, ElapsedEventArgs.Empty); 

या

_timer.Raise(item => item.Elapsed += null, EventArgs.Empty); 

दोनों काम नहीं करेगा।

अद्यतन:

यहाँ बात है कि मेरे लिए काम किया है। ध्यान दें कि यह उपयोगी नहीं है यदि आप ईवेंट हैंडलर को जानकारी पास करने की कोशिश कर रहे हैं जैसे जॉन ने टिप्पणियों में बताया। मैं बस सिस्टम.Timers.Timer वर्ग के लिए रैपर नकली करने के लिए इसका उपयोग कर रहा हूँ।

_timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs); 

अंत में, यदि आपको घटना तर्कों का उपयोग करने की आवश्यकता है, तो यह हमेशा मदद नहीं करेगा क्योंकि यह हमेशा शून्य होगा। हालांकि, यह एकमात्र तरीका है क्योंकि ElapsedEventArgs में केवल एक आंतरिक कन्स्ट्रक्टर है।

+0

"प्रकार की वस्तु 'System.EventArgs' जारी रख सकते हैं 'System.Timers.ElapsedEventArgs' टाइप करने के लिए को परिवर्तित करें "- कौन सा हिस्सा अस्पष्ट है? – Groo

+0

मुझे अभी भी यह त्रुटि मिलती है भले ही मैं ElapsedEventArgs पास करता हूं। मैं उस घटना को कैसे बढ़ा सकता हूं? –

+0

आपके 'ITimer' इंटरफ़ेस में 'ElapsedEventHandler' वास्तव में' System.Timers.ElapsedEventHandler' है? – Groo

उत्तर

10

ElapsedEventArgs एक निजी निर्माता है और instantiated नहीं किया जा सकता है।

यदि आप का उपयोग करें:

timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs); 

फिर हैंडलर एक अशक्त पैरामीटर recevie और उसके SignalTime संपत्ति खो देंगे:

private void WhenTimerElapsed(object sender, ElapsedEventArgs e) 
{ 
    // e is null. 
} 

आप कुछ मामलों में इस पैरामीटर चाहते हो सकता है।

इस को हल करने और इसे और अधिक परीक्षण योग्य बनाने के लिए, मैं भी ElapsedEventArgs के लिए एक आवरण बनाया है, और बना इंटरफ़ेस का उपयोग करें:

public class TimeElapsedEventArgs : EventArgs 
{ 
    public DateTime SignalTime { get; private set; } 

    public TimeElapsedEventArgs() : this(DateTime.Now) 
    { 
    } 

    public TimeElapsedEventArgs(DateTime signalTime) 
    { 
     this.SignalTime = signalTime; 
    } 
} 

public interface IGenericTimer : IDisposable 
{ 
    double IntervalInMilliseconds { get; set; } 

    event EventHandler<TimerElapsedEventArgs> Elapsed; 

    void StartTimer(); 

    void StopTimer(); 
} 

कार्यान्वयन बस अपने आप ही घटना वास्तविक से डेटा प्राप्त करने में सक्रिय होगा टाइमर घटना:

public class TimerWrapper : IGenericTimer 
{ 
    private readonly System.Timers.Timer timer; 

    public event EventHandler<TimerElapsedEventArgs> Elapsed; 

    public TimeSpan Interval 
    { 
     get 
     { 
      return this.timer.Interval; 
     } 
     set 
     { 
      this.timer.Interval = value; 
     } 
    } 

    public TimerWrapper (TimeSpan interval) 
    { 
     this.timer = new System.Timers.Timer(interval.TotalMilliseconds) { Enabled = false }; 
     this.timer.Elapsed += this.WhenTimerElapsed; 
    } 

    private void WhenTimerElapsed(object sender, ElapsedEventArgs elapsedEventArgs) 
    { 
     var handler = this.Elapsed; 
     if (handler != null) 
     { 
      handler(this, new TimeElapsedEventArgs(elapsedEventArgs.SignalTime)); 
     } 
    } 

    public void StartTimer() 
    { 
     this.timer.Start(); 
    } 

    public void StopTimer() 
    { 
     this.timer.Stop(); 
    } 

    public void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.disposed) 
     { 
      if (disposing) 
      { 
       this.timer.Elapsed -= this.WhenTimerElapsed; 
       this.timer.Dispose(); 
      } 

      this.disposed = true; 
     } 
    } 
} 

अब, आप को सरल बनाने और इस घटना के नकली सुधार कर सकते हैं:

timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs()); 

var yesterday = DateTime.Now.AddDays(-1); 
timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs(yesterday)); 

लिखने के लिए कम कोड, काम करने में आसान और पूरी तरह से ढांचे से decoupled।

+1

+1 अच्छा काम ... –

+1

मैं बस अपने सिर को नहीं प्राप्त कर सकता हूं क्यों ElapsedEventArgs का निजी कन्स्ट्रक्टर है, इस पागलपन की आवश्यकता है। वैसे भी, मार्गदर्शन के लिए आप दोनों को धन्यवाद।@JoanComasFdz, यदि आप टाइमरवापर के पूर्ण कार्यान्वयन को दिखाते हैं तो यह सहायक होगा। मैंने अंततः इसे हल किया, लेकिन इसमें कुछ मिनट लग गए। – Brett

+0

@ ब्रेट कोड अपडेट किया गया :) – JoanComasFdz

5

Moq QuickStart guide घटनाओं पर एक अनुभाग है। मुझे लगता है कि आप उपयोग करेंगे

mock.Raise(m => m.Elapsed += null, new ElapsedEventArgs(...)); 
+0

क्लाइंट क्लास से असाइन किए गए हैंडलर को प्रतीत नहीं होता है? क्या मैं कुछ भूल रहा हूँ? क्या मैं हैंडलर को बचाने के लिए मजाक नहीं कहूंगा? –

+0

@ UfukHacıoğulları: मेरा मानना ​​है कि नकली सिर्फ किसी भी हैंडलर को याद रखेगा। मैं सुझाव दूंगा कि आप अपने * असली * कोड से बाहर निकलने से शुरू हो जाएं, और केवल नमूना कार्यक्रम के साथ प्रयोग करें जब तक कि आपने यह साबित नहीं किया कि मोक कैसे काम करता है, फिर अपने असली कोड पर वापस जाएं। –

+0

यह सभी –

0

हाल ही में इस रहे थे, वहीं आप प्रतिबिंब का उपयोग कर एक ElapsedEventArgs निर्माण कर सकते हैं:

public ElapsedEventArgs CreateElapsedEventArgs(DateTime signalTime) 
    { 
     var e = FormatterServices.GetUninitializedObject(typeof(ElapsedEventArgs)) as ElapsedEventArgs; 
     if (e != null) 
     { 
      var fieldInfo = e.GetType().GetField("signalTime", BindingFlags.NonPublic | BindingFlags.Instance); 
      if (fieldInfo != null) 
      { 
       fieldInfo.SetValue(e, signalTime); 
      } 
     } 

     return e; 
    } 

इस तरह से आप मूल ElapsedEventHandler प्रतिनिधि नहीं कर सकते का उपयोग कर

var yesterday = DateTime.Now.AddDays(-1); 
timer.Raise(item => item.Elapsed += null, CreateElapsedEventArgs(yesterday)); 
संबंधित मुद्दे