2011-06-29 9 views
6

いくつかのイベントを持つクラスをテストするのにNUnitとMoqを使用していますが、イベントが発生したかどうかをテストする最善の方法を見つけようとしています。私はこの解決策を考え出しましたが、テスト用のインターフェイスを作成する必要があるため、ちょっと汚いと感じました。どのようにしても、コードを少なくして同じことをすることも、インターフェースを作成することもできません。NUnitとMoqを使用して単体テストイベントを改善する方法は?

それほど悪くはないが、誰かがより良い解決策を持っているかもしれないと感じている。 すべてのアイデアは評価されています。おかげさまで

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

答えて

4

このテストはモックなしで行うのが簡単です。テストフィクスチャをイベント加入者として倍増させる。

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

私がテストしていたイベントごとに新しいフラグと新しいメソッドを作成する必要があります。それはかなりの膨らみを加えるでしょう。この例では、同じインターフェースを使用できます。しかし、私はあなたが言っていることを見る。 –

+0

@Dusty Lau - あなたがテストしたいのはイベントがトリガーされているので、汎用フラグ(NotificationReceived)とハンドラを使用できます。インターフェイスをテストしている場合など。 INotifyPropertyChangedを使用すると、インターフェイスの実装に関係するユーティリティクラスPropertyChangeListenerを記述できます。 – Gishu

0

以下は、私が過去によく使用した方法のスニペットです。イベントが発生するたびに、(私の場合は)ConnectionChangedEventArgsのインスタンスをリスト<に追加するだけです。その後、いくつのイベントが解雇されたかについてのアサートが行われます。うまくいけば、あなたはアイデアを得て、あなたが望むなら自分のニーズに適応させることができます。

[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

私は扱うことができますが、理由を述べてください! – Andy

3

私はこれについてmoqはまったく必要ないと思います。イベントに登録し、解雇された回数(または解雇回数)を評価することができます:

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)); 
    } 
関連する問題