Unit Testing Race Situation

In the current project I’m working on, we are intensively writing unit tests with 100% code coverage following TDD.

In this post I’m going to share one of very exciting situations that I faced couple of days ago while working on a module which is supposed to initialise database on fist access.

While the first caller is waiting for the database to be initialised, the second caller needs to wait as well and do not trigger the initialise method again. After the wait is over the second caller needs to know that the database is initialised and continue the normal work.

The fact of putting the initialisation in the database client is not the centre of this post.

There are couple of ways of tackling this but IMO the best way is to actually make a race situation happen in your unit test. Some developers do this by firing an action and delaying that by putting the first thread to sleep and fire the second thread while the first thread is asleep. The biggest problem is that how long do you want to put the first thread to sleep. On different machine the process of running the unit tests in the test runner takes different time to run. So you should either introduce a very long delay (seconds) or a short one that runs on your machine but may fail on the build server.

Here is how I solved this issue:

 

I used two indefinite while loops. I know it sounds very ugly but hey it’s unit test and not the implementation of the service itself. By using the loops I’m simply letting the thread asleep to be variable at the minimum that ensures the race situation happens.

I let the second thread to start in the loop of the first thread and then let the first thread to finish in the loop of the second thread. That way the second call is always guaranteed to hit the race situation.

With that solved, I then assert that my methods are run as expected.

Please note that I have injected my own mocked Semaphore so I can handle the checks without using fakes.

Here is some parts of the implementation:

 

I’ve used the following libs/frameworks:
  • xUnit
  • NSubstitute
  • NFluent

Here is the unit test in two ways:

Method 1: Mocking the Semaphore and handling the wait and release in order to make sure the race condition happens:

 

Method 2: Inject a semaphore and let it do its job while we force the racing situation to happen using only the config:

 

Leave a Reply

Your email address will not be published. Required fields are marked *