【问题标题】:Trying to Unit Test an Event with JustMock尝试使用 JustMock 对事件进行单元测试
【发布时间】:2014-01-22 17:11:07
【问题描述】:

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

我确实想测试 Event 本身,因为它会调用各种需要大量工作来模拟的内部函数。

下面是一些示例代码:

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

这是我希望喜欢写但不能写的测试:

[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:\BizObjectTests\EventMocking.cs

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

【问题讨论】:

    标签: c# unit-testing events telerik justmock


    【解决方案1】:

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

    您有几个备选方案。如果您在专用于该目的的方法中引发事件(如在您的示例中),那么您可以简单地模拟该方法。因此,在您的示例中,变为:

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

    如果这不可能,那么您可以模拟将处理程序添加到事件的方法(调用 Sample += ... 时调用的方法)。你可以这样做:

    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 事件。

    【讨论】:

      猜你喜欢
      • 2023-03-27
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      相关资源
      最近更新 更多