zoukankan      html  css  js  c++  java
  • NSubstitute完全手册(十四)引发事件

    有时,引发被替代的类型中定义的事件时非常必要的。例如下面这个例子:

     1     public interface IEngine
     2     {
     3       event EventHandler Idling;
     4       event EventHandler<LowFuelWarningEventArgs> LowFuelWarning;
     5       event Action<int> RevvedAt;
     6     }
     7 
     8     public class LowFuelWarningEventArgs : EventArgs
     9     {
    10       public int PercentLeft { get; private set; }
    11       public LowFuelWarningEventArgs(int percentLeft)
    12       {
    13         PercentLeft = percentLeft;
    14       }
    15     }

    在 .NET 中,事件是非常有意思的功能,因为你不能像操作其他成员似地进行传递。相反地,你只能添加或移除事件处理器,NSubstitute 正是使用了这个添加事件处理器的语法来引发事件。

     1     [TestMethod]
     2     public void Test_RaisingEvents_RaiseEvent()
     3     {
     4       var engine = Substitute.For<IEngine>();
     5 
     6       var wasCalled = false;
     7       engine.Idling += (sender, args) => wasCalled = true;
     8 
     9       // 告诉替代实例引发异常,并携带指定的sender和事件参数
    10       engine.Idling += Raise.EventWith(new object(), new EventArgs());
    11 
    12       Assert.IsTrue(wasCalled);
    13     }

    在上面的例子中,我们不能真实地了解到我们所引发事件的发送者和参数,仅是知道它被调用了。在这种条件下,NSubstitute 通过为我们的事件处理器创建所需的参数,来使该操作更便捷些。

     1     [TestMethod]
     2     public void Test_RaisingEvents_RaiseEventButNoMindSenderAndArgs()
     3     {
     4       var engine = Substitute.For<IEngine>();
     5 
     6       var wasCalled = false;
     7       engine.Idling += (sender, args) => wasCalled = true;
     8 
     9       engine.Idling += Raise.Event();
    10       Assert.IsTrue(wasCalled);
    11     }

    当参数没有默认构造函数时引发事件

    NSubstitute 不总是能够创建事件参数。如果事件的参数没有默认的构造函数,你可能不得不使用 Raise.EventWith<TEventArgs>(...) 来创建事件参数,例如下面例子中的 LowFuelWarning 事件。如果没有提供事件的发送者,则 NSubstitute 会创建。

     1     [TestMethod]
     2     public void Test_RaisingEvents_ArgsDoNotHaveDefaultCtor()
     3     {
     4       var engine = Substitute.For<IEngine>();
     5 
     6       int numberOfEvents = 0;
     7       engine.LowFuelWarning += (sender, args) => numberOfEvents++;
     8 
     9       // 发送事件,并携带指定的事件参数,未指定发送者
    10       engine.LowFuelWarning += Raise.EventWith(new LowFuelWarningEventArgs(10));
    11       // 发送事件,并携带指定的事件参数,并指定发送者
    12       engine.LowFuelWarning += Raise.EventWith(new object(), new LowFuelWarningEventArgs(10));
    13 
    14       Assert.AreEqual(2, numberOfEvents);
    15     }

    引发Delegate事件

    有时事件会通过委托来声明,而没有继承自 EventHandler<> 或 EventHandler。这种事件可以通过使用 Raise.Event<TypeOfEventHandlerDelegate>(arguments)来引发。NSubstitute 会尝试和猜测该委托所需的参数,但如果没成功,NSubstitute 会告诉你具体需要提供哪个参数。

    下面这个示例演示了引发 INotifyPropertyChanged 事件,该事件使用 PropertyChangedEventHandler 委托并需要2个参数。

     1     [TestMethod]
     2     public void Test_RaisingEvents_RaisingDelegateEvents()
     3     {
     4       var sub = Substitute.For<INotifyPropertyChanged>();
     5       bool wasCalled = false;
     6 
     7       sub.PropertyChanged += (sender, args) => wasCalled = true;
     8 
     9       sub.PropertyChanged += Raise.Event<PropertyChangedEventHandler>(
    10         this, new PropertyChangedEventArgs("test"));
    11 
    12       Assert.IsTrue(wasCalled);
    13     }

    引发Action事件

    在 IEngine 示例中,RevvedAt 事件被声明为 Action<int>。这是委托事件的另外一种形式,我们可以使用 Raise.Event<Action<int>>() 来引发该事件。

     1     [TestMethod]
     2     public void Test_RaisingEvents_RaisingActionEvents()
     3     {
     4       var engine = Substitute.For<IEngine>();
     5 
     6       int revvedAt = 0;
     7       engine.RevvedAt += rpm => revvedAt = rpm;
     8 
     9       engine.RevvedAt += Raise.Event<Action<int>>(123);
    10 
    11       Assert.AreEqual(123, revvedAt);
    12     }

    NSubstitute 完全手册

  • 相关阅读:
    Admin注册和路由分发详解
    自定义Xadmin
    苑昊老师的博客
    pip 国内源 配置
    Django模型层(2)
    Django 中间件
    Django form表单
    整理的最全 python常见面试题(基本必考)
    AJAX
    Cookie、Session和自定义分页
  • 原文地址:https://www.cnblogs.com/gaochundong/p/nsubstitute_raising_events.html
Copyright © 2011-2022 走看看