代码之家  ›  专栏  ›  技术社区  ›  Jason Irwin

是否应该对事件处理程序进行单元测试

  •  4
  • Jason Irwin  · 技术社区  · 15 年前

    4 回复  |  直到 15 年前
        1
  •  2
  •   TrueWill    15 年前

    我绝不会说有人对事件处理程序进行单元测试是“错误的”。就我个人而言,我会遵循“测试可能会破坏的东西”的理念,但不会。

    我所看到的事件代码一贯错误的主要原因是单元测试无法捕捉到的东西-“On”方法只会是:

    if (MyEventHandler != null)
        MyEventHandler(this, e);
    

    第二个常见错误是人们为“e”事件数据参数传递null;这可以进行测试。

    如果你没有Cwalina&Abrams的框架设计指南第二版,现在就买吧。它将告诉您如何每次正确地编写事件代码,如何正确地编写Dispose模式,以及其他许多事情。

        2
  •  0
  •   Reed Copsey    15 年前

    public event EventHandler MyEvent;
    protected void OnMyEvent()
    {
        // Raise MyEvent here
    }
    

    那么,对MyEvent的测试实际上是OnMyEvent测试的一部分,因为您要做的唯一“测试”是验证事件是否正确引发。

    通常,测试一个事件意味着订阅它,并做一些应该(或不应该)引发它的操作。

        3
  •  0
  •   lance    15 年前

    我读了你的问题,不知道你问的是处理程序的主体,还是处理程序实际上是否被正确绑定以处理事件。

    正如您所说,处理程序的主体应该简单地调用您已经测试过的另一个方法(如果它是公共的)。

        4
  •  0
  •   Mike Perrenoud    12 年前

    Click Button 来自Microsoft的类。首先要注意的是,他们使用 EventHandlerList

    protected EventHandlerList Events {
        get { 
            if (events == null) { 
                events = new EventHandlerList(this);
            } 
            return events;
        }
    }
    
    ...
    
    public event EventHandler Click {
        add {
            Events.AddHandler(EventClick, value); 
        }
        remove { 
            Events.RemoveHandler(EventClick, value); 
        }
    } 
    

    现在请注意实际的提升方法 OnClick

    protected virtual void OnClick(EventArgs e) { 
        Contract.Requires(e != null);
        EventHandler handler = (EventHandler)Events[EventClick]; 
        if (handler != null) handler(this, e); 
    }
    

    ... 别担心线路 Contract.Requires(e != null); 事件处理程序列表 如果那个处理程序不是 null

    here . 这实际上是微软的一个很好的指南。

    现在, ,我相信事件应该被测试,这里有一个我过去用过的机制。。。

    private ManualResetEvent _eventRaised = new ManualResetEvent(false);
    
    [TestMethod]
    public void TestSomething()
    {
        _eventRaised.Reset();
    
        // hook up the event to the target being tested
        // NOW, in the event handler, issue _eventRaised.Set();
    
        // do something to raise the event
    
        _eventRaised.WaitOne();
    }