开发者

Better way to unit test events using NUnit and Moq?

开发者 https://www.devze.com 2023-03-16 13:46 出处:网络
I am using NUnit and Moq to test开发者_如何学C a class that has some events and I am trying to find the best way to test whether or not an event was fired.I came up with this solution but it feels kin

I am using NUnit and Moq to test开发者_如何学C a class that has some events and I am trying to find the best way to test whether or not an event was fired. I came up with this solution but it feels kinda dirty since I have to create an interface for the test. Any way I can do the same thing with less code or not have to create an interface?

Its not that bad but I feel someone may have a better solution. Any ideas are appreciated. Thanks.

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


This test seems easier to do without mocks. Make the test fixture double as an event subscriber.

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


I think, you don't need moq for this at all. You can just register for the events and evaluate if they have been fired (or the number of times they were fired):

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


Below is a snippet of a way I have used in the past to good effect. It simply adds (in my case) instances of ConnectionChangedEventArgs to a List<> each time the event is fired. The assert is then made on how many events were fired. Hopefully you get the idea and can adapt it to your own needs if you desire.

[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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号