2011-06-29 5 views
6

Tôi đang sử dụng NUnit và Moq để kiểm tra một lớp học có một số sự kiện và tôi đang cố gắng tìm cách tốt nhất để kiểm tra xem một sự kiện có được kích hoạt hay không. Tôi đã đưa ra giải pháp này nhưng nó cảm thấy kinda bẩn vì tôi phải tạo ra một giao diện cho thử nghiệm. Bất kỳ cách nào tôi có thể làm điều tương tự với mã ít hơn hoặc không phải tạo ra một giao diện?Cách tốt hơn để kiểm tra các sự kiện đơn vị sử dụng NUnit và Moq?

Nó không phải là xấu nhưng tôi cảm thấy ai đó có thể có một giải pháp tốt hơn. Bất kỳ ý tưởng nào được đánh giá cao. Cảm ơn.

[Test] 
    public void StartedAndStoppedEventsShouldFireWhenStartedAndStopped() 
    { 
     var mockStartedEventSubscriber = new Mock<IEventSubscriber>(); 
     var mockStoppedEventSubscriber = new Mock<IEventSubscriber>(); 

     _NetworkMonitor.Started += mockStartedEventSubscriber.Object.Handler; 
     _NetworkMonitor.Stopped += mockStoppedEventSubscriber.Object.Handler; 

     _NetworkMonitor.Start(); 
     _NetworkMonitor.Stop(); 

     Func<bool> func =() => { return (eNetworkMonitorStatus.Stopped == _NetworkMonitor.Status); }; 
     Utilities.WaitUntilTrue(func, _NetworkMonitor.Interval * 2, 10); 

     _NetworkMonitor.Started -= mockStartedEventSubscriber.Object.Handler; 
     _NetworkMonitor.Stopped -= mockStoppedEventSubscriber.Object.Handler; 

     mockStartedEventSubscriber.Verify(h => h.Handler(_NetworkMonitor, EventArgs.Empty), Times.Once()); 
     mockStoppedEventSubscriber.Verify(h => h.Handler(_NetworkMonitor, EventArgs.Empty), Times.Once()); 
    } 

    public interface IEventSubscriber 
    { 
     void Handler(object sender, EventArgs e); 
    } 

Trả lời

4

Kiểm tra này có vẻ dễ làm hơn mà không có mocks. Làm cho vật cố thử nghiệm tăng gấp đôi với tư cách là người đăng ký sự kiện.

_networkMonitor.Started += this.SetStartedFlag; // a private method which sets a flag in the test fixture. 
_networkMonitor.Start(); 
Assert.That(StartedFlag, Is.True); 
+0

Tôi sẽ phải tạo một cờ mới và phương pháp mới cho mỗi sự kiện tôi đã thử nghiệm. Điều đó sẽ thêm một chút sưng lên. Trong ví dụ này tôi có thể sử dụng cùng một giao diện. Nhưng tôi thấy những gì bạn đang nói. –

+0

@Dusty Lau - Bạn có thể sử dụng cờ chung (NotificationReceived) và trình xử lý vì tất cả những gì bạn muốn kiểm tra là sự kiện được kích hoạt. Nếu bạn đang thử nghiệm một giao diện, ví dụ: INotifyPropertyChanged, bạn có thể viết một lớp tiện ích PropertyChangeListener làm việc với bất kỳ việc thực hiện giao diện nào. – Gishu

0

Dưới đây là đoạn trích mà tôi đã sử dụng trong quá khứ để có hiệu quả tốt. Nó chỉ đơn giản là thêm (trong trường hợp của tôi) trường hợp của ConnectionChangedEventArgs vào một danh sách <> mỗi khi sự kiện được kích hoạt. Xác nhận sau đó được thực hiện về số lượng sự kiện đã được kích hoạt. Hy vọng rằng bạn có được ý tưởng và có thể thích nghi nó với nhu cầu của riêng bạn nếu bạn mong muốn.

[Test] 
public void GoodConnectionRaisesConnectionChangedEvent() 
{ 
    const int EXPECTED = 1; 
    List<ConnectionChangedEventArgs> ev = new List<ConnectionChangedEventArgs>(); 

    // Mocks and setup stuff here... 

    using (PlcController pc = new PlcController(mock.Object)) 
    { 
     pc.ConnectionChanged += delegate(object sender, ConnectionChangedEventArgs e) 
     { 
      ev.Add(e); 
     }; 

     pc.Connect(); 
    } 

    Assert.That(ev.Count, Is.EqualTo(EXPECTED)); 
} 
+0

Phiếu bầu tôi có thể xử lý, nhưng hãy bình luận về lý do tại sao! – Andy

3

Tôi nghĩ, bạn không cần moq cho điều này chút nào. Bạn chỉ có thể đăng ký cho các sự kiện và đánh giá nếu chúng đã bị sa thải (hoặc số lần chúng bị bắn):

public class NetworkMonitor 
    { 
     public event EventHandler Started; 
     public event EventHandler Stopped; 

     public void Start() 
     { 
      var handler = Started; 
      if (handler != null) 
       handler(this, EventArgs.Empty); 
     } 

     public void Stop() 
     { 
      var handler = Stopped; 
      if (handler != null) 
       handler(this, EventArgs.Empty); 
     } 

    } 

    [Test] 
    public void StartedAndStoppedEventsShouldFireWhenStartedAndStopped() 
    { 

     NetworkMonitor classUnderTest = new NetworkMonitor(); 
     bool startedWasFired = false; 
     int stoppedWasFired = 0; 
     classUnderTest.Started += (o, e) => { startedWasFired = true; }; 
     classUnderTest.Stopped += (o, e) => { stoppedWasFired++; }; 

     classUnderTest.Start(); 
     Assert.That(startedWasFired); 
     classUnderTest.Stop(); 
     Assert.That(stoppedWasFired, Is.EqualTo(1)); 
    }