Writing Unit or Integration Tests That Rely on Events Firing
Posted by Keith Elder | Posted in .Net, C# | Posted on 22-10-2010
For the past week or so I’ve been working on wrapping the Sonic API to simplify it for developers at my company. The API itself is pretty much a straight port from Java. There is nothing C# about the API. For example no enumerations, no generics, no nothing. This means when you are using the API you see functions that take a parameter that is just an integer since there are no enumerations for example. That wouldn’t be so bad if the code was documented in the proper C# way but it isn’t. So, instead of having 100+ developers at work learn how Sonic works I have been coding up several scenarios that we need to support for the business.
In my quest to wrap the Sonic API into a more C# centric approach I needed to write some tests obviously to make sure things were working. Primarily these are integration tests as each test relies upon connecting to a Sonic dev environment.
If you aren’t familiar with Sonic it is an enterprise messaging platform. It does pub/sub, supports queues, fault tolerate and so on. I think the stock market even uses Sonic to route messages so it has a proven track record.
One of the scenarios I had to cover was I needed to send a message to a queue and then have that message pulled out of the queue on the other side, processed and acknowledged. In order to do this there is one object that sends a message, and another object that is listening for a message(s). But how do you write a test that waits on an event to happen? Well, it turns out we’d done this before in other tests but I couldn’t for the life of me remember how. So here’s how it works.
Using an EventWaitHandle we can wait on an event to occur. First is to create a handle.
1: EventWaitHandle handle = new ManualResetEvent(false);
Using the handle we can tell it to WaitOne() which blocks the current thread until the WaitHandle receives a signal.
1: handle.WaitOne();
Then inside our event we simply call handle.Set() (this is the signal).
Putting all of this together we can write an integration test that sends a message to Sonic and then waits for that message to come through. Obviously the Sonic piece doesn’t really matter, the important piece here is how to get a test to wait for an event. Putting it all together it looks like this.
1: [TestMethod]
2: public void Can_Send_To_Queue_And_Receive_Message_From_Queue()
3: {
4: EventWaitHandle handle = new ManualResetEvent(false);
5: SonicQueueSender sender = new SonicQueueSender(Helpers.SonicQueueArgs);
6: string sendMsg = "test";
7: sender.SendMessage(sendMsg, SonicDeliveryMode.NonPersistent);
8: SonicQueueReceiver consumer = new SonicQueueReceiver(Helpers.SonicQueueArgs);
9: string receiveMsg = "";
10: consumer.MessageRecieved += (mySender, args) =>
11: {
12: TextMessage txtMsg = (TextMessage)args.Message;
13: receiveMsg = txtMsg.getText();
14: handle.Set();
15: };
16: consumer.StartListener();
17: handle.WaitOne();
18: Assert.AreEqual(receiveMsg, sendMsg);
19: }
Hope this helps someone out.
Thanks for this! is very nice information, cooll!!