As explained in the comments, events in .Net are synchronous, so with the system as shown in the question, there is no possibility of something going wrong. However, a more interesting question would be: how would you handle testing if the scenario was in fact asynchronous?
This is a scenario that often pops up in games whose game logic runs on a timer tick.
The idea is that instead of telling the game logic to perform an action (like block.MissThrow()
in the original question) you post a message to the game logic telling it that the action should be performed at its earliest convenience. The message is stored in a queue, and the call to post the message returns immediately. (So, obviously, if you were to try and test for the reaction of the game logic immediately after posting the message, you would be out of luck, because the game logic would not have reacted yet.)
Then later, a timer event kicks in, (say, at the same frequency as the frame rate of the game,) at which point the game logic reads all messages from its queue, does whatever it needs to do, and issues notifications.
These notifications may be placed in other queues, or they may be delivered directly to their recipients, but in either case the notifications will be asynchronous since the issuing of the notifications happens as a result of responding to a timer event to read actions from a queue.
So, how would you test the game logic in such a scenario?
The answer is: by introducing an abstraction of the event system, so that we can have control over it, and then manipulating the event system from within the tests.
Here is how it would look like:
EventSystem eventSystem = new EventSystem();
GameLogic gameLogic = new GameLogic( eventSystem );
List<UpdateEventArgs> updateEventArgs = new ArrayList<UpdateEventArgs>();
gameLocic.Updated += (sender, args) => updateEventArgs.Add( args );
gameLogic.postAction1();
eventSystem.DoTick();
Assert( updateEventArgs.Count == 1 );
Assert( updateEventArgs[0].Equals(so-and-so) );
updateEventArgs.Clear();
gameLogic.postAction2();
eventSystem.DoTick();
Assert( updateEventArgs.Count == 1 );
Assert( updateEventArgs[0].Equals(such-and-such) );
updateEventArgs.Clear();
gameLogic.postAction3();
eventSystem.DoTick();
Assert( updateEventArgs.Count == 1 );
Assert( updateEventArgs[0].Equals(this-and-that) );
updateEventArgs.Clear();
...
In an actual production runtime scenario, eventSystem.DoTick()
would be invoked every 33 milliseconds for a rate of 30 frames per second, but in the tests we invoke it as we need it, so as to test the actions that are supposed to be performed by the game logic during the tick event.
The added benefit of doing things this way is that our tests run instantaneously, instead of having to wait several tens of milliseconds between each tick test.
handler?.Invoke()
the runtime will execute each registered handler in turn before returning to the next line afterhandler?.Invoke
.