Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test a method that spawns threads?

I am fairly new to TDD but have been using it for long enough to understand how to use mocks, stubs, dependency injection, inversion of control to solve 'similar' problems... but for some reason I feel very uneasy about using dependency injection and passing in an 'IThread' (or similar).

To give it some basic context - I am trying to add unit tests to a legacy application and I am unsure of how to unit test a class who's constructor spawns two threads.

Is the only option to use dependency injection?

If so what about the functionality that the threads bring? As it stands the threads both run while(true) loops and never exit the loop (unless the application is terminating). Inside the loops there are reasonable chunks of code and it's this code that I really want to have under test.

To make matters worse I don't want to pull all the functionality out of the loops and into public methods (I'm only testing public methods as my tests exist in another project) as it will really decrease the easy of use of the class elsewhere in the code.

Any suggestions?

like image 865
InvertedAcceleration Avatar asked Jan 20 '10 10:01

InvertedAcceleration


People also ask

How do you test threads?

To test multi-thread functionality, let the multiple instances of the application or program to be tested be active at the same time. Run the multi-thread program on different hardware. Thread testing is a form of session testing for which sessions are formed of threads.

How do I test a concurrent code?

One good way to test this is to make sure you have access to a multi-cpu machine, then run your test for as long a time/with as many iterations as possible. For example if you have a multithreaded producer consumer algorithm, fill the queue with a good sized list and use 2x as many threads as you might in production.

Why is testing multithreaded concurrent code so difficult?

Multi-threaded programming is probably the most difficult solution to concurrency. It basically is quite a low level abstraction of what the machine actually does. There's a number of approaches, such as the actor model or (software) transactional memory, that are much easier.


1 Answers

Could you pull the functionality into internal methods and use InternalsVisibleTo instead? Even if you'd really want them to be private, this is a reasonable compromise solution.

If your threads would normally run forever, that does make it very hard to test... and it sounds like you really should be testing the "what the threads do" part separately, if they don't depend on being in separate threads.

One option which is occasionally useful is to have an IScheduler type of interface - ask that to execute an action wherever it sees fit; the production one would create a new thread, but your test one could run the action within the existing thread (or on a thread you had control over within your test code). I'm not sure that's appropriate for your situation here, where the thread would run forever, but you might want to think about it in other situatoins.

like image 81
Jon Skeet Avatar answered Sep 28 '22 16:09

Jon Skeet