簡體   English   中英

使用 NUnit 和 Moq 對事件進行單元測試的更好方法?

[英]Better way to unit test events using NUnit and Moq?

我正在使用 NUnit 和 Moq 來測試具有一些事件的 class,並且我正在嘗試找到測試是否觸發事件的最佳方法。 我想出了這個解決方案,但感覺有點臟,因為我必須為測試創建一個接口。 有什么方法可以用更少的代碼做同樣的事情,或者不必創建接口?

它還不錯,但我覺得有人可能有更好的解決方案。 任何想法表示贊賞。 謝謝。

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

如果沒有模擬,這個測試似乎更容易完成。 使測試夾具兼作事件訂閱者。

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

我認為,您根本不需要最小起訂量。 您可以只注冊事件並評估它們是否已被觸發(或它們被觸發的次數):

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

下面是我過去使用的一種效果很好的方法的片段。 每次觸發事件時,它只是將 ConnectionChangedEventArgs 的實例(在我的情況下)添加到 List<> 中。 然后斷言觸發了多少事件。 希望你能得到這個想法,如果你願意,可以根據自己的需要進行調整。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM