【问题标题】:Better way to unit test events using NUnit and Moq?使用 NUnit 和 Moq 对事件进行单元测试的更好方法?
【发布时间】:2011-06-29 22:24:45
【问题描述】:

我正在使用 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);
    }

【问题讨论】:

    标签: c# unit-testing events nunit moq


    【解决方案1】:

    如果没有模拟,这个测试似乎更容易完成。使测试夹具兼作事件订阅者。

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

    【讨论】:

    • 我必须为我正在测试的每个事件创建一个新标志和新方法。这会增加相当多的臃肿。在这个例子中,我可以使用相同的界面。但我明白你在说什么。
    • @Dusty Lau - 您可以使用通用标志 (NotificationReceived) 和处理程序,因为您要测试的只是事件被触发。如果您正在测试一个接口,例如INotifyPropertyChanged,您可以编写一个实用程序类 PropertyChangeListener,它可以与接口的任何实现一起使用。
    【解决方案2】:

    我认为,您根本不需要最小起订量。您只需注册事件并评估它们是否已被触发(或它们被触发的次数):

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

    【讨论】:

      【解决方案3】:

      下面是我过去使用的一种效果良好的方法的 sn-p。每次触发事件时,它只是将 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));
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-01
        • 2021-10-15
        • 1970-01-01
        • 2018-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多