I’m developing the simple client server protocol code that I’m harvesting in a test driven manner. Although the code exists, as such, and I’m harvesting it rather than inventing it from scratch the harvesting is taking the “best” ideas from several similar implementations to create the version that will form part of the framework’s example code. As such I’m treating this just like a new development and, mostly, writing my tests first. This has worked well, as usual, and has allowed me to mercilessly refactor whilst I go as I decide to incorporate features from different versions of the protocol handlers into this ‘demo’ version.
One thing that I find especially satisfying when testing is when I come across some code that is hard to test but that I test anyway. Today’s example of that is the blocking call on the client connector.
The asynchronous, fire and forget, style request was easy to test. The connector is constructed on an asynchronous stream and it writes its messages to this stream when it needs to. Testing the asynchronous request was simple; call the function on the connector to send the message and then check that the correct data has been passed to the mocked out stream that I’m using in my test harness. Likewise the polled request/response pair were easy to test; test the request in the same way that we tested the asynchronous request and then test a response by pushing data into the connector so that it has a complete response and then calling the polling method on the connector to make sure that the response is available. The synchronous call is different though as the whole idea is that it blocks inside until the response arrives or a timeout occurs. Testing the timeout code path first helped me to structure a test which blocked for a very short time inside the synchronous method call and then confirmed that the call had failed as expected. Once I had that code structure I relied on a pattern that I’ve been using for some time for these kind of tests.
First I created a class that included a thread. The class’s constructor starts the thread and the thread itself then waits either for a shutdown signal or for a ‘start processing’ signal. The test then passes the synchronous call arguments to the thread and signals it to start processing. The stream has an event within it that allows us to wait for the synchronous call to write the message it and once that has happened the test continues and we can push a response into the connector and it can then wait on the synchronous call returning inside the test thread by waiting on an event that the test thread sets when the call completes. The test thread is blocked inside of the synchronous call but this returns now that a response is available. Once it has returned the test thread signals the ‘call complete’ event and the test continues.
This structure allows us to test all aspects of the blocking call without having the test block or requiring any external interference. The test, the mocks and the test thread communicate using events that can be set and waited on and so we allow the code under test to run in a controlled manner. Using this approach we can also make sure that the synchronous call operates correctly when the communication’s channel is reset whilst a call is in progress, etc.
Of course it helps that my test framework supports this style of testing, but since I’m still using a fairly basic, hand crafted, test framework that’s not hard to achieve. I also have the advantage of writing my own mocks which means that I can get them to do anything I want (such as setting events when particular calls occur). Yes it probably takes longer for me to build the mocks in the first place, but any code that uses a library also tends to use its mocks which helps.
How do you test complicated blocking code?