This is a problem me and my team faces in almost all of the projects. Testing certain parts of the application with JUnit is not easy and you need to start early and to stick to it, but that’s not the question I’m asking. The actual problem is that with n-Threads, locking, possible exceptions within the threads and shared objects the task of testing is not as simple as testing the class, but testing them under endless possible situations within threading.
To be more precise, let me tell you about the design of one of our applications:
When a user makes a request several threads are started that each analyse a part of the data to complete the analysis, these threads run a certain time depending on the size of the chunk of data (which are endless and of uncertain quality) to analyse, or they may fail if the data was insufficient/lacking quality. After each completed its analysis they call upon a handler which decides after each thread terminates if the collected analysis-data is sufficient to deliver an answer to the request.
All of these analysers share certain parts of the applications (some parts because the instances are very big and only a certain number can be loaded into memory and those instances are reusable, some parts because they have a standing connection, where connecting takes time, ex.gr. sql connections) so locking is very common (done with reentrant-locks). While the applications runs very efficient and fast, it’s not very easy to test it under real-world conditions.
What we do right now is test each class and it’s predefined conditions, but there are no automated tests for interlocking and synchronization, which in my opionion is not very good for quality insurances.
Given this example how would you handle testing the threading, interlocking and synchronization?
3
Since I was never really happy with the answers I received I had already given up and solved the concurrency issues with time but without having actual tests that proved that they were not existing any more. But today I stumbled upon a solution for the problem.
Links that explain writing those kind of tests:
- https://github.com/junit-team/junit/wiki/Multithreaded-code-and-concurrency
- http://tempusfugitlibrary.org/recipes/2012/05/20/testing-concurrent-code/
- http://www.planetgeek.ch/2009/08/25/how-to-find-a-concurrency-bug-with-java/
In short all these tests initialize Runnable and start them at exactly the same time to achieve a maximum concurrency-load, this way concurrency issues should be exposed.
2
Sounds like you’re doing integration testing not unit testing
In general, when you unit test you split the code into its smallest parts and test each one in isolation. Sometimes, you need to emulate dependencies – a process called mocking. Good mocking libraries include JMockit (for mocking absolutely anything including making String mutable) or Mockito if your needs are normal.
These days multithreaded applications in Java should be built upon the java.util.concurrent
packages and have ExecutorService
at their heart. Unless your needs are very specific there is no real requirement to access Thread
directly any more.
Given a design based on the concurrency packages you should be able to decompose your analysis and construct isolated unit tests for them. This approach should greatly simplify your code, and make the behaviour of threads a lot more predictable than it currently sounds.
1