Tuesday, August 23, 2005

Add Events to NMock

While using View Observer on my last project we needed a way to raise events for unit testing. The best solution turned out to be stubs; however, while we were evaluating options Levi Khatskevitch created a DynamicMockWithEvents class.

DynamicMockWithEvents inherits from NMock's DynamicMock, but it also contains support for raising events from a mock. To raise an event from a mock simply call the RaiseEvent method with the event name and any optional args.
public class DynamicMockWithEvents : DynamicMock
{
private const string ADD_PREFIX = "add_";
private const string REMOVE_PREFIX = "remove_";

private readonly EventHandlerList handlers;
private readonly Type mockedType;

public DynamicMockWithEvents(Type type) : base(type)
{
handlers = new EventHandlerList();
mockedType = type;
}

public override object Invoke(string methodName, params object[] args)
{
if (methodName.StartsWith(ADD_PREFIX))
{
handlers.AddHandler(GetKey(methodName, ADD_PREFIX), (Delegate) args[0]);
return null;
}
if (methodName.StartsWith(REMOVE_PREFIX))
{
handlers.RemoveHandler(GetKey(methodName, REMOVE_PREFIX), (Delegate) args[0]);
return null;
}
return base.Invoke(methodName, args);
}

private static string GetKey(string methodName, string prefix)
{
return string.Intern(methodName.Substring(prefix.Length));
}

public void RaiseEvent(string eventName, params object[] args)
{
Delegate handler = handlers[eventName];
if (handler == null)
{
if (mockedType.GetEvent(eventName) == null)
{
throw new MissingMemberException("Event " + eventName + " is not defined");
}
else if (Strict)
{
throw new ApplicationException("Event " + eventName + " is not handled");
}
}
handler.DynamicInvoke(args);
}
}
Post a Comment