2012-01-20 36 views
13

Tôi đang cố gắng kích hoạt trình xử lý sự kiện được gán cho bộ hẹn giờ. Làm thế nào tôi có thể kiểm tra phương pháp riêng tư này ở đây?Làm cách nào để chạy trình xử lý sự kiện được gán cho mô hình?

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

Lớp khách hàng chỉ định trình xử lý sự kiện cho đối tượng này. Tôi muốn kiểm tra logic trong lớp này.

_timer.Elapsed += ResetExpiredCounters; 

Và phương pháp giao là tin

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

Tôi muốn có xử lý sự kiện này trong mô hình của tôi và chạy nó bằng cách nào đó. Tôi có thể làm cái này như thế nào?

Cập nhật:

tôi nhận ra tôi đã nâng cao sự kiện này trước khi tôi được giao xử lý sự kiện. Tôi sửa chữa điều đó nhưng tôi vẫn nhận được lỗi này:

tôi nâng nó như thế này:

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

hoặc

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

Cả hai sẽ không hoạt động.

Cập nhật:

Đây là điều mà làm việc cho tôi. Lưu ý rằng nó không hữu ích nếu bạn đang cố chuyển thông tin tới trình xử lý sự kiện như Jon đã chỉ ra trong các bình luận. Tôi chỉ sử dụng nó để giả mạo trình bao bọc cho lớp System.Timers.Timer.

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

Cuối cùng, điều này sẽ không giúp ích gì nếu bạn cần sử dụng đối số sự kiện vì nó sẽ luôn luôn rỗng. Tuy nhiên, đó là cách duy nhất vì ElapsedEventArgs chỉ có một hàm tạo bên trong.

+0

"Object kiểu 'System.EventArgs' không thể được chuyển đổi để nhập 'System.Timers.ElapsedEventArgs' "- Phần nào không rõ ràng? – Groo

+0

Tôi vẫn nhận được lỗi đó ngay cả khi tôi vượt qua ElapsedEventArgs. Làm thế nào tôi có thể nâng cao sự kiện đó? –

+0

Có phải 'ElapsedEventHandler' trong giao diện' ITimer' của bạn thực sự 'System.Timers.ElapsedEventHandler'? – Groo

Trả lời

10

ElapsedEventArgs có hàm tạo riêng và không thể khởi tạo được.

Nếu bạn sử dụng:

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

Sau đó xử lý sẽ recevie một tham số rỗng và mất tài sản SignalTime của nó:

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

Bạn có thể muốn tham số này trong một số trường hợp.

Để giải quyết việc này và làm cho nó kiểm chứng nhiều hơn, tôi cũng đã tạo ra một wrapper cho ElapsedEventArgs, và làm cho giao diện sử dụng nó:

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(); 
} 

Việc thực hiện chỉ đơn giản là sẽ cháy sự kiện riêng của mình nhận được dữ liệu từ thực hẹn giờ sự kiện:

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; 
     } 
    } 
} 

Bây giờ, bạn có thể đơn giản hóa và cải thiện mô hình của sự kiện này:

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

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

Ít mã để viết, dễ làm việc và hoàn toàn tách rời khỏi khung công tác.

+1

+1 Công việc tuyệt vời ... –

+1

Tôi chỉ đơn giản là không thể hiểu được tại sao ElapsedEventArgs có một hàm tạo riêng, đòi hỏi sự điên rồ này. cảm ơn cả hai bạn vì sự hướng dẫ[email protected], nó sẽ rất hữu ích nếu bạn cho thấy việc thực hiện đầy đủ của TimerWrapper. Cuối cùng tôi đã sắp xếp nó ra, nhưng phải mất một vài phút. – Brett

+0

@Brett Code được cập nhật :) – JoanComasFdz

5

Moq QuickStart guide có phần về sự kiện. Tôi nghĩ bạn sẽ sử dụng

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

Trình xử lý được chỉ định từ lớp máy khách dường như không chạy? Tui bỏ lỡ điều gì vậy? Tôi không nên nói để chế giễu tiết kiệm xử lý? –

+0

@ UfukHacıoğulları: Tôi tin rằng giả sẽ chỉ nhớ bất kỳ trình xử lý nào được thêm vào. Tôi sẽ khuyên bạn nên bắt đầu bằng cách ra khỏi mã * thực * của bạn, và chỉ thử nghiệm với một sự kiện mẫu cho đến khi bạn đã chứng minh cách Moq hoạt động, sau đó quay trở lại với mã thực sự của bạn. –

+0

Dường như nó không chạy trình xử lý sự kiện ở tất cả –

0

xử lý này thời gian gần đây, bạn có thể xây dựng một ElapsedEventArgs sử dụng phản ánh:

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; 
    } 

Bằng cách này bạn có thể tiếp tục sử dụng ElapsedEventHandler đại biểu gốc

var yesterday = DateTime.Now.AddDays(-1); 
timer.Raise(item => item.Elapsed += null, CreateElapsedEventArgs(yesterday)); 
Các vấn đề liên quan