试图用JustMock进行单位测试事件



我正在尝试使用忽略事件的JustMock编写单元测试。

i做不是想要测试事件本身,因为它调用了各种内部功能,这些功能需要大量的努力才能模拟。

这是示例代码的快速示例:

public class Sample
{
    public delegate void OneParameterFunction(int someVar);
    public event OneParameterFunction TheEvent;               
    public Sample()
    {            
        TheEvent += CallMe;
    }
    public void CallMe(int someVar)
    {
        Debug.WriteLine("CallMe was fired with parameter: " + someVar);
    }
    public void FireEvent()
    {
        // do stuff, business logic here...
        if (TheEvent != null)
            TheEvent(3);
    }
}

这是我要写的测试 love ,但不能:

[TestClass]
class EventMocking
{
    [TestMethod]
    public void DoNothingOnEvent()
    {
        var s = new Sample();
        Mock.Arrange(() => s.TheEvent(Arg.AnyInt))            
            .DoNothing();
        Mock.Arrange(() => s.CallMe(Arg.AnyInt))
            .OccursNever();
        s.FireEvent();
        Mock.Assert(() => s.CallMe(Arg.AnyInt));
    }
}

但是我收到以下编译器错误:

Error   1   The event 'Sample.TheEvent' can only appear on the left hand side of += or -= (except when used from within the type 'Sample')  C:BizObjectTestsEventMocking.cs

有人对如何阻止事件传播有任何建议吗?我也不想出于多种原因来 Mock.Create<T>,一个是我会再次设置更多的测试数据/对象。

不可能模拟委托调用本身,因为它是由JIT内部实现的。

您有几个替代选项。如果您以专门用于该目的的方法(如样本中)提出事件,则可以简单地模拟该方法。因此,在您的样本中变为:

Mock.Arrange(() => s.FireEvent()).DoNothing();

如果不可能,则可以模拟将处理程序添加到事件中的方法(调用示例 = ...时调用)。您可以这样做:

var mock = Mock.Create<Sample>(); // we need this just for the following arrangement
Mock.ArrangeSet(() => mock.TheEvent += null).IgnoreInstance().IgnoreArguments().DoNothing();
var real = new Sample(); // TheEvent += CallMe will now do nothing
real.FireEvent(); // TheEvent is empty

最后,作为第三种选项,您可以在某个时候使用反射从事件中删除所有处理程序,您知道事件即将被触发,或者没有其他人会附加到它:

new PrivateAccessor(real).SetField("TheEvent", null);
real.FireEvent(); // TheEvent is null right now

警告:最后一个选项取决于编译器的实现。它将适用于C#代码中的事件声明,但对VB事件不起作用。