使用NUnit和Moq对事件进行单元测试的更好方法是什么?

时间:2011-06-29 22:24:45

标签: c# unit-testing events 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);
    }

3 个答案:

答案 0 :(得分:4)

如果没有模拟,这个测试似乎更容易。使测试夹具成为事件订户。

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

答案 1 :(得分: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));
    }

答案 2 :(得分:0)

下面是我过去使用过的方式的片段,效果很好。它只是将(在我的情况下)ConnectionChangedEventArgs的实例添加到List&lt;&gt;每次事件被触发。然后断言发出了多少事件。希望你能得到这个想法,如果你愿意,可以根据自己的需要进行调整。

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