Javascript Coding

Testing multi-threaded code using synchronisation events

Multi-threading is a vital part of programming, offering many performance benefits that most applications today could not do without using some aspect of it. Any developer who has interacted with the operations or business side of the fence when deploying applications will know that testing an application is crucial to keeping it working and, consequently, keeping everyone happy. There are so many ways that bugs can creep in, and if you are solely relying on manual testing, you will have a challenging daily life turning up to work.

Unit testing must be seen as a priority to ensure your survival in the daily cage fight called the workplace. Deploying an application in a state that is guaranteed to work is necessary for stable blood pressure and no bags under the eyes. Managers, losing the team is inevitable in situations where the leadership cannot demonstrate competency. In cases where the code using multiple threads to do some fantastic work, this is all the more essential to have well-tested code.

Here is a simple but effective technique using synchronisation contexts to test multithreaded code to ensure that you can sleep at night with neither the development or operations team spending all their time orchestrating who gets the blame for the failure.

Let us first start by created our test subject. A simple event class which has a Publish method where I will be testing that the publish method is called for our test to be successful.

				
					public class CustomEvent
{
	private readonly Action _onPublish;

	public CustomEvent(Action onPublish)
	{
		_onPublish = onPublish;
	}

	public void Publish()
	{
		_onPublish?.Invoke();
	}
}
				
			

The CustomEvent class accepts an Action in its constructor, which is called when the Publish event completes.

 

Our main (Process/UI) thread will use the onPublish Action to do something once the Publish operation is finished. This technique is very useful when having an event-driven application without blocking the UI or another thread.

 

This pattern can be employed in many variations; just use your imagination.

				
					public class CustomEventShould
{
	[Test]
	public void RunTheOnPublishEventAfterPublishing()
	{
		// Arrange
		bool isPublished = false;
		CustomEvent @event = new CustomEvent(() => isPublished = true);

		// Act
		ThreadPool.QueueUserWorkItem(state => @event.Publish());

		// Assert
		Assert.IsTrue(isPublished);
	}
}
				
			

Now we need to test. We write an NUnit test where we run the Publish event on another thread to simulate real-world application behaviour; however, the test fails. The Publish event was not called before the main thread proceeded to assert.

 

How do we solve this problem?

				
					public class CustomEventShould
{
	[Test]
	public void RunTheOnPublishEventAfterPublishing()
	{
		// Arrange
		bool isPublished = false;
		AutoResetEvent syncEvent = new AutoResetEvent(false);
			CustomEvent @event = new CustomEvent(() =>
		{
			isPublished = true;
			syncEvent.Set();
		});

		// Act
		ThreadPool.QueueUserWorkItem(state => @event.Publish());
		syncEvent.WaitOne();

		// Assert
		Assert.IsTrue(isPublished);
	}
}
				
			

Adding an AutoResetEvent in a non-signalled state, we can pause the unit test thread and wait for the publish even to signal that it is complete by calling the Set method on the synchronisation event. Now we experience the soothing benefit of having the onPublish event in the constructor. My fellow coders, this is how you test multithreaded code rather than looking at the logs to see a spike in errors.

 

It always works, no need for Thread.Sleep nightmares and erratic behaviour; now, nobody can lay the blame at your door—the beauty of unit testing.

 

Seriously though, you got to change the culture of that company — life is too short.

Leave a Reply