我有事件和提升方法,如下所示:
public class Events {
public event EventHandler<CustomEventArgs> Succeed;
public virtual void OnSucceed(object sender, params object[] data)
{
CustomEventArgs args = new CustomEventArgs(data);
EventHandler<CustomEventArgs> _succeed = Succeed;
if (_succeed != null)
{
_succeed(sender, args);
}
}}
我为 OnSucceed 方法创建了单元测试(使用FluentAssertions):
[Test]
public void SucceedShouldNotBeRaisedTest()
{
Events events = new Events();
events.MonitorEvents();
events.OnSucceed(this,"somedata");
events.ShouldNotRaise("Succeed");
}
由于没有该活动的订阅者,我希望它不会提出成功事件
但测试失败,因为成功事件被提升。这有什么问题?!
答案 0 :(得分:1)
当您致电events.MonitorEvents();
时, FluentAssertions 会自动订阅公开事件,以检测事件何时被引发。
您的测试失败,因为您的情况将始终评估为true
:if (_succeed != null)
。测试时,事件将始终与null
现在我想建议您遵循Jon Skeet提出的方法:
public event EventHandler<CustomEventArgs> Succeed = delegate { } ;
通过上述事件声明,您的活动永远不会是null
(无法从班级外部分配活动)
注意:您可以将事件背后的委托指定为其类 中的null,如下所示:
this.Succeed = null;
以上语句将事件后面的委托指定为null,而不是事件本身。通常你不需要做这样的事情,但是如果你这样做,你将不得不重新初始化这样的事件:
this.Succeed = null;
this.Succeed = delegate { };
如果您遵循这些建议,您的活动将永远不会为空,您无需再调用if(this.MyEvent != null)
条件来提升您的活动。 (请注意,这种情况完全是技术性的,与域本身无关。)
现在您已删除了技术条件,您可以实际关注域规则,以决定何时举起活动。
最后一步是删除:if (_succeed != null)
并添加一个条件,指明是否应该根据您当前的域引发该事件
if(shouldRaiseEvent)
{
EventHandler<CustomEventArgs> _succeed = Succeed;
_succeed(...);
}
对于您的测试,您只需要使用所需条件配置您的受试者,以便提高或不提高您的活动。
完整样本:
public class Events {
public event EventHandler<CustomEventArgs> Succeed = delegate { };
public virtual void OnSucceed(object sender, params object[] data)
{
if (/*[optional] here your domain condition that will indicate if the event should be raised*/)
{
// this is a best practice to deal with multi-threading situations
var _succeed = this.Succeed;
var args = new CustomEventArgs(data);
_succeed(sender, args);
}
}
}