[英]How to unit test an event subscribtion with NUnit
您好,我想知道是否有人知道我的問題的答案:
考慮以下代碼
class TheHandler
{
...
Public EventHandler myRealWorldEvent;
...
}
class TheSubscriber
{
private TheHandler myHandler = new TheHandler();
public subscribeToHandler()
{
myHandler.myRealWorldEventHandler += OnSomethingHappens;
}
...
pirvate OnSomeThingHappens()
{
...
}
}
我的問題是->如何測試(僅使用NUnit)OnSomethingHappens已訂閱myRealWorldEventHandler。 我無法更改SUT /生產代碼,也無法模擬(Moq / Nmock等)。 有人知道我的問題的解決方案嗎?
最好的祝福,
正通
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);
如果您必須處理大量舊系統測試(例如,私有成員,靜態成員-一些免費框架無法很好地處理或根本無法解決的問題 )-我建議您看一下諸如TypeMock或JustMock之類的工具。
有同樣的問題。 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);
}
“不”方法:
public static void assertNotSubscribed<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;
}
if (inappropriate) return;
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.Null);
}
和調用:
assertSubscribed<EventHandler>(handler, subscriber);
assertNotSubscribed<EventHandler>(handler, subscriber);
assertSubscribed<EventHandler>(handler, subscriber, "myRealWorldEvent");
assertNotSubscribed<EventHandler>(handler, subscriber, "myRealWorldEvent");
不要為代碼樣式約定而煩惱我,但此方法看起來足夠緊湊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.