Multithread testing
Testing multithreaded objects are quite complex. I have an object that keeps care of executing some action in a different thread, monitor progress of that action, and then signal to the caller progress and return value. for testing purpose I write a simple action like this.
|
|
This class inherits from AsyncOperationBase, it makes a simple iteration, raises 10 progress event and returns OOK. What I want to test is OperationManager Object that have a similar function
|
|
The IProgressConsumer is the interface that will accepts the callback and contains a couple of methods called SignalProgress and Return. Now I want to mock this interface, pass the mock object to the Start method of OperationManager and verify that progress and return methods are called correctly. Since Start method runs the action in a different thread, I need to make some synchronization stuff in the test. Here is it:
|
|
First of all I have some base code that keeps track of creating the Rhino repository, and verifying the expectation once the test code was run. Based on this structure I need a ManualResetEvent to make sure that the mock verification phase is called only when the asynchronous action is completed. The test uses this structure
- creates a ManualResetEvent in false status
- create mocks objects, sets the expectations
- use the WhenCalled method of Rhino Mocks in the Return expectation, in this way I can signal the event object created in point 1.
- Exercise the sut (call start method)
- wait for a certain number of seconds for the event to be signaled
In this way I’m sure that the verification phase is run only after the action completed the execution.
This is one of the most common problem when testing asynchronous components, you need to be sure to begin the verification phase only when all the asynchronous operations of the sut are completed. Standard unit testing follows the Four Phase Test pattern.
When the sut executes its operation asynchronously this pattern needs to be changed slightly
To make this possible you should structure the sut in such a way that it is possible for the test to know when all the asynchronous operations are completed. In my example this is straightforward, because the sut signals to the caller the return value of the action, when you have fire and forget actions where there is no notification sent to the caller, implementing this pattern can be a little more complicated.
Alk.
Tags: testing