C# 如何使用NUnit对事件订阅进行单元测试

C# 如何使用NUnit对事件订阅进行单元测试,c#,unit-testing,events,event-handling,nunit,C#,Unit Testing,Events,Event Handling,Nunit,你好,我想知道是否有人知道我的问题的答案: 考虑以下代码 class TheHandler { ... Public EventHandler myRealWorldEvent; ... } class TheSubscriber { private TheHandler myHandler = new TheHandler(); public subscribeToHandler() { myHandler.myReal

你好,我想知道是否有人知道我的问题的答案:

考虑以下代码

class TheHandler
{
    ...
    Public EventHandler myRealWorldEvent;
    ...


}

class TheSubscriber
{
    private TheHandler myHandler = new TheHandler();

    public subscribeToHandler()
    { 
        myHandler.myRealWorldEventHandler += OnSomethingHappens;

    }

     ...

    pirvate OnSomeThingHappens()
    {
       ...
    }
}
我这里的问题是->如何测试(仅使用NUnit)某些事件是否已订阅myRealWorldEventHandler。我无法更改SUT/生产代码,也无法模拟(Moq/Nmock等)。有人知道我的问题的解决办法吗

致以最良好的祝愿


Zhengtonit

NUnit不这样做-测试某个私有处理程序是否订阅了某个私有字段。这里面有太多私事。然而,这并不是说你不能从反思中得到一点帮助。请注意,这不是一个漂亮的代码:

var subscriber = new TheSubscriber();
var handlerField = typeof(TheSubscriber)
    .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
    // if field with such name is not present, let it fail test
    .First(f => f.Name == "myHandler");

var handlerInstance = handlerField.GetValue(subscriber);
var someEventField = typeof(TheHandler)
    .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
    .First(f => f.Name == "myRealWorldEvent");

var eventInstance = (EventHandler) someEventField.GetValue(handlerInstance);
var subscribedMethod = eventInstance
    .GetInvocationList()
    .FirstOrDefault(d => d.Method.Name == "OnSomethingHappens");

Assert.That(subscribedMethod, Is.Not.Null);

如果您需要处理大量的遗留系统测试(即私有成员、静态成员——自由框架无法很好地处理或根本无法处理这些问题)——我建议您看看诸如或之类的工具。

NUnit不会这样做——测试某个私有处理程序是否订阅了某个私有字段。这里面有太多私事。然而,这并不是说你不能从反思中得到一点帮助。请注意,这不是一个漂亮的代码:

var subscriber = new TheSubscriber();
var handlerField = typeof(TheSubscriber)
    .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
    // if field with such name is not present, let it fail test
    .First(f => f.Name == "myHandler");

var handlerInstance = handlerField.GetValue(subscriber);
var someEventField = typeof(TheHandler)
    .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
    .First(f => f.Name == "myRealWorldEvent");

var eventInstance = (EventHandler) someEventField.GetValue(handlerInstance);
var subscribedMethod = eventInstance
    .GetInvocationList()
    .FirstOrDefault(d => d.Method.Name == "OnSomethingHappens");

Assert.That(subscribedMethod, Is.Not.Null);

如果您需要处理大量遗留系统测试(例如,私有成员、静态成员——自由框架无法很好地处理或根本无法处理这些问题)——我建议您看看诸如或之类的工具。

也有同样的问题。来自jimmy_keen的代码在旧的.NET中无法正常工作。通过编写助手方法解决了此问题:

public static void assertSubscribed<EventHandlerType>(object handler, object subscriber, string eventName = null) {
    var inappropriate = false;
    try {
        if (!typeof (EventHandlerType).IsSubclassOf(typeof (Delegate)) ||
            typeof (EventHandlerType).GetMethod("Invoke").ReturnType != typeof (void))
            inappropriate = true;
    } catch (AmbiguousMatchException) {
        inappropriate = true;
    } finally {
        if (inappropriate) throw new Exception("Inappropriate Delegate: " + typeof (EventHandlerType).Name);
    }

    var handlerField = subscriber.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
        .First(h => h.FieldType.IsInstanceOfType(handler));

    var handlerInstance = handlerField == null ? null : handlerField.GetValue(subscriber);
    var eventField = handlerInstance == null ? null : handlerInstance.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
        .First(f => (f.FieldType.IsAssignableFrom(typeof (EventHandlerType)) &&
                     (eventName == null || eventName.Equals(f.Name))));

    var eventInstance = eventField == null ? null : (Delegate)eventField.GetValue(handlerInstance);
    var subscribedMethod = eventInstance == null
        ? null 
        :eventInstance.GetInvocationList().FirstOrDefault(
            d => d.Method.DeclaringType != null && d.Method.DeclaringType.IsInstanceOfType(subscriber));

    Assert.That(subscribedMethod, Is.Not.Null);
}
publicstaticvoidassertsubscribed(对象处理程序、对象订阅者、字符串eventName=null){
var=false;
试一试{
if(!typeof(EventHandlerType).IsSubclassOf(typeof(Delegate))||
typeof(EventHandlerType).GetMethod(“Invoke”).ReturnType!=typeof(void))
不恰当=正确;
}捕获(模糊匹配异常){
不恰当=正确;
}最后{
if(不适当)抛出新异常(“不适当的委托:+typeof(EventHandlerType).Name);
}
var handlerField=subscriber.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.First(h=>h.FieldType.IsInstanceOfType(handler));
var handlerInstance=handlerField==null?null:handlerField.GetValue(订户);
var eventField=handlerInstance==null?null:handlerInstance.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.First(f=>(f.FieldType.IsAssignableFrom(typeof(EventHandlerType))&&
(eventName==null | | eventName.Equals(f.Name));
var eventInstance=eventField==null?null:(委托)eventField.GetValue(handlerInstance);
var subscribedMethod=eventInstance==null
无效的
:eventInstance.GetInvocationList().FirstOrDefault(
d=>d.Method.DeclaringType!=null&&d.Method.DeclaringType.IsInstanceOfType(订阅者));
Assert.That(subscribedMethod,Is.Not.Null);
}
“非”方法:

publicstaticvoidassertnotsubscribed(对象处理程序、对象订阅者、字符串eventName=null){
var=false;
试一试{
if(!typeof(EventHandlerType).IsSubclassOf(typeof(Delegate))||
typeof(EventHandlerType).GetMethod(“Invoke”).ReturnType!=typeof(void))
不恰当=正确;
}捕获(模糊匹配异常){
不恰当=正确;
}
如果(不适当)返回;
var handlerField=subscriber.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.First(h=>h.FieldType.IsInstanceOfType(handler));
var handlerInstance=handlerField==null?null:handlerField.GetValue(订户);
var eventField=handlerInstance==null?null:handlerInstance.GetType()
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.First(f=>(f.FieldType.IsAssignableFrom(typeof(EventHandlerType))&&
(eventName==null | | eventName.Equals(f.Name));
var eventInstance=eventField==null?null:(委托)eventField.GetValue(handlerInstance);
var subscribedMethod=eventInstance==null
无效的
:eventInstance.GetInvocationList().FirstOrDefault(
d=>d.Method.DeclaringType!=null&&d.Method.DeclaringType.IsInstanceOfType(订阅者));
Assert.That(subscribedMethod,Is.Null);
}
和调用:

assertSubscribed<EventHandler>(handler, subscriber);
assertNotSubscribed<EventHandler>(handler, subscriber);
assertSubscribed<EventHandler>(handler, subscriber, "myRealWorldEvent");
assertNotSubscribed<EventHandler>(handler, subscriber, "myRealWorldEvent");
assertSubscribed(经办人、订户);
资产未认购(经办人、认购人);
assertSubscribed(处理程序、订户、“myRealWorldEvent”);
assertNotSubscribed(处理程序、订户、“myRealWorldEvent”);

不要因为代码样式约定而打扰我,但是这个方法看起来足够紧凑。

也有同样的问题。来自jimmy_keen的代码在旧的.NET中无法正常工作。通过编写助手方法解决了此问题:

public static void assertSubscribed<EventHandlerType>(object handler, object subscriber, string eventName = null) {
    var inappropriate = false;
    try {
        if (!typeof (EventHandlerType).IsSubclassOf(typeof (Delegate)) ||
            typeof (EventHandlerType).GetMethod("Invoke").ReturnType != typeof (void))
            inappropriate = true;
    } catch (AmbiguousMatchException) {
        inappropriate = true;
    } finally {
        if (inappropriate) throw new Exception("Inappropriate Delegate: " + typeof (EventHandlerType).Name);
    }

    var handlerField = subscriber.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
        .First(h => h.FieldType.IsInstanceOfType(handler));

    var handlerInstance = handlerField == null ? null : handlerField.GetValue(subscriber);
    var eventField = handlerInstance == null ? null : handlerInstance.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
        .First(f => (f.FieldType.IsAssignableFrom(typeof (EventHandlerType)) &&
                     (eventName == null || eventName.Equals(f.Name))));

    var eventInstance = eventField == null ? null : (Delegate)eventField.GetValue(handlerInstance);
    var subscribedMethod = eventInstance == null
        ? null 
        :eventInstance.GetInvocationList().FirstOrDefault(
            d => d.Method.DeclaringType != null && d.Method.DeclaringType.IsInstanceOfType(subscriber));

    Assert.That(subscribedMethod, Is.Not.Null);
}
publicstaticvoidassertsubscribed(对象处理程序、对象订阅者、字符串eventName=null){
var=false;
试一试{
if(!typeof(EventHandlerType).IsSubclassOf(typeof(Delegate))||
typeof(EventHandlerType).GetMethod(“Invoke”).ReturnType!=typeof(void))
不恰当=正确;
}捕获(模糊匹配异常){
不恰当=正确;
}最后{
if(不适当)抛出新异常(“不适当的委托:+typeof(EventHandlerType).Name);
}
var handlerField=subscriber.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.First(h=>h.FieldType.IsInstanceOfType(handler));
var handlerInstance=handlerField==null?null:handlerField.GetValue(订户);
var eventField=handlerInstance==null?null:handlerInstance.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.First(f=>(f.FieldType.IsAssignableFrom(typeof(EventHandlerType))&&
(eventName==null | | eventName.Equals(f.Name));
var eventInstance=eventField==null?null:(委托)eventField.GetV