Neil Bourgeois posted an excellent
article on this. I find myself often need EventHandler<TEventArgs> in addition to EventHandler, and also I would like to write
Will(Hookup.Event(mockEvent))
because it reads more natually so easier to understand:
1:MockEvent mockEvent = new MockEvent();
2:Expect.Once.On(mockProvider).EventAdd("EffectiveUserChanged", Is.Anything)
3: .Will(Hookup.Event(mockEvent));
4:mockEvent.Raise(mockProvider, EventArgs.Empty);
Here I added a static class
Hookup
and generic versions of Neil's classes.
1: /// <summary>
2: /// http://blog.gravityfree.ca/2007/03/raising-events-in-nmock-20.html
3: /// </summary>
4: /// <author>Neil Bourgeois</author>
5: /// <author>Kenneth Xu</author>
6: /// <seealso cref="MockEvent{TEventArgs}"/>
7: /// <seealso cref="Hookup"/>
8: public class MockEvent
9: {
10: private EventHandler _handler;
11:
12: public void Initialize(EventHandler handler)
13: {
14: this._handler = handler;
15: }
16:
17: public void Raise()
18: {
19: Raise(this, EventArgs.Empty);
20: }
21:
22: public void Raise(object source, EventArgs e)
23: {
24: _handler.Invoke(source, e);
25: }
26:
27: }
28:
29: /// <summary>
30: /// http://blog.gravityfree.ca/2007/03/raising-events-in-nmock-20.html
31: /// </summary>
32: /// <author>Neil Bourgeois</author>
33: /// <author>Kenneth Xu</author>
34: /// <seealso cref="MockEvent"/>
35: /// <seealso cref="Hookup"/>
36: public class MockEvent<TEventArgs> where TEventArgs : EventArgs
37: {
38: private EventHandler<TEventArgs> _handler;
39:
40: public void Initialize(EventHandler<TEventArgs> handler)
41: {
42: this._handler = handler;
43: }
44:
45: public void Raise(object source, TEventArgs e)
46: {
47: _handler.Invoke(source, e);
48: }
49:
50: }
51:
52: /// <summary>
53: /// See BusinessContextTest for an example.
54: /// </summary>
55: /// <author>Kenneth Xu</author>
56: /// <seealso cref="MockEvent"/>
57: /// <seealso cref="MockEvent{TEventArgs}"/>
58: public static class Hookup
59: {
60: public static IAction Event(MockEvent mockEvent)
61: {
62: return new MockEventHookup(mockEvent);
63: }
64:
65: public static IAction Event<TEventArgs>(MockEvent<TEventArgs> mockEvent)
66: where TEventArgs : EventArgs
67: {
68: return new MockEventHookup<TEventArgs>(mockEvent);
69: }
70:
71: /// <summary>
72: /// http://blog.gravityfree.ca/2007/03/raising-events-in-nmock-20.html
73: /// </summary>
74: /// <author>Neil Bourgeois</author>
75: /// <seealso cref="MockEvent"/>
76: /// <seealso cref="MockEventHookup{TEventArgs}"/>
77: private class MockEventHookup : IAction
78: {
79: private readonly MockEvent mockEvent;
80:
81: public MockEventHookup(MockEvent mockEvent)
82: {
83: this.mockEvent = mockEvent;
84: }
85:
86: public void Invoke(Invocation invocation)
87: {
88: EventHandler handler = invocation.Parameters[0] as EventHandler;
89: if (handler == null)
90: throw new Exception("Unknown event handler type: " + invocation.Parameters[0].GetType());
91: mockEvent.Initialize(handler);
92: }
93:
94: public void DescribeTo(TextWriter writer)
95: {
96: // do nothing
97: }
98: }
99:
100: /// <summary>
101: /// http://blog.gravityfree.ca/2007/03/raising-events-in-nmock-20.html
102: /// </summary>
103: /// <author>Neil Bourgeois</author>
104: /// <seealso cref="MockEvent{TEventArgs}"/>
105: /// <seealso cref="MockEventHookup"/>
106: private class MockEventHookup<TEventArgs> : IAction
107: where TEventArgs : EventArgs
108: {
109: private readonly MockEvent<TEventArgs> mockEvent;
110:
111: public MockEventHookup(MockEvent<TEventArgs> mockEvent)
112: {
113: this.mockEvent = mockEvent;
114: }
115:
116: public void Invoke(Invocation invocation)
117: {
118: EventHandler<TEventArgs> handler = invocation.Parameters[0] as EventHandler<TEventArgs>;
119: if (handler == null)
120: throw new Exception("Unknown event handler type: " + invocation.Parameters[0].GetType());
121: mockEvent.Initialize(handler);
122: }
123:
124: public void DescribeTo(TextWriter writer)
125: {
126: // do nothing
127: }
128: }
129: }
130: