How to write a JUnit test case for testing threads and events

I have Java code that runs on a single (main) thread. From the main thread, I create a new thread in which I make a server call. After the server call is completed, I do some work in the new thread, after which the code joins the main thread.

I am using eclipse Jobs to make a server call.

I want to know how to write a JUnit test case for this.

+11
source share
7 answers

You may need to restructure your code so that it can be easily tested.

I can see several different areas for testing:

  • Chain Management Code: code that starts thread (s) and possibly awaits results
  • "Work" code runs in a thread
  • Concurrency issues that can occur when using multiple threads actively.

Structure your implementation so that the flow control code is agnostic about Worker details. You can then use Mock Workers to enable flow control testing β€” for example, Mock Worker, which doesn’t work in a specific way, allows you to check for specific paths in the control code.

Inject Worker code so that it can run in isolation. You can use unit test yourself, using mocks for the server.

For concurrency testing, the links provided by Abhijeet Kashnia will help.

+10
source

This is what ConcurrentUnit created. General use:

  • Create multiple threads
  • Waiting or lowering the main thread
  • Perform assertions from worker threads (which are returned to the main thread through ConcurrentUnit)
  • Resume the main thread from one of the worker threads after all claims are completed

See the ConcurrentUnit page for more information.

+6
source

I suggest you use a mocking structure to confirm that the server call is actually made. Regarding thread block testing : Testing multi-threaded applications

+2
source

The resources provided by Abhijeet Kashnia may help, but I'm not sure what you are trying to achieve.

You can do unit testing with mocks to test your code that will not test concurrency but provide coverage. You can write an integration test to make sure that the threads are created and combined as you expect. However, this will not guarantee concurrency problems. Most concurrent problems are caused by synchronization errors that are not predictable and therefore cannot be tested accurately.

+2
source

I assume that you might have made your mocking code and you might want to do a simple integration test to make sure your call to the server works.

One of the difficulties in testing threads comes from their very nature - they are parallel. This means that you are forced to write JUnit test code, which is forced to wait until your thread completes its work before testing the results of your code. This is not a good way to test the code and may be unreliable, but usually it means that you have an idea of ​​whether the code is working.

As an example, your code might look something like this:

@Test public void myIntegrationTest() throws Exception { // Setup your test // call your threading code Results result = myServerClient.doThreadedCode(); // Wait for your code to complete sleep(5); // Test the results assertEquals("some value",result.getSomeValue()); } private void sleep(int seconds) { try { TimeUnit.SECONDS.sleep(seconds); } catch (InterruptedException e) { e.printStackTrace(); } } 

I really don't like to do this and prefer ridicule and agree with the other answers. But if you need to check your threads, then this is one of the approaches that I find.

+2
source

Here is my solution for testing the asynchrone method that used thread.start:

 public class MyClass { public void doSomthingAsynchrone() { new Thread(() -> { doSomthing(); }).start(); } private void doSomthing() { } } @RunWith(PowerMockRunner.class) @PrepareForTest(MyClass.class) public class MyClassTest { ArgumentCaptor<Runnable> runnables = ArgumentCaptor.forClass(Runnable.class); @InjectMocks private MyClass myClass; @Test public void shouldDoSomthingAsynchrone() throws Exception { // create a mock for Thread.class Thread mock = Mockito.mock(Thread.class); // mock the 'new Thread', return the mock and capture the given runnable whenNew(Thread.class).withParameterTypes(Runnable.class) .withArguments(runnables.capture()).thenReturn(mock); myClass.doSomthingAsynchrone(); runnables.getValue().run(); /** * instead of 'runnables.getValue().run();' you can use a real thread.start * * MockRepository.remove(Thread.class); * Thread thread = new Thread(runnables.getValue()); * thread.start(); * thread.join(); **/ verify(myClass, times(1)).doSomthing(); } } 
0
source

When your only problem is waiting for a result, use the ExecutorService to spawn your threads. It can accept work tasks like Runnable and Callable . When you use the latter, you are given a Future object in return, which you can use to wait for the result. In any case, you should consider using ExecutorService, since, as I understand it, you create a lot of threads, and this is an ideal use case for executor services.

 class AnyClass { private ExecutorService threadPool = Executors.newFixedThreadPool(5); public List<Future<Integer>> anyMethod() { List<Future> futures = new ArrayList<>(); futures.add(threadPool.submit(() -> { // Do your job here return anyStatusCode; })); futures.add(threadPool.submit(() -> { // Do your other job here return anyStatusCode; })); return futures; } } 

And the test class:

 class TestAnyClass { @Test public void testAnyMethod() { AnyClass anyObject = new AnyClass(); List<Future<Integer>> futures = anyObject.anyMethod(); CompletableFuture[] completable = futures.toArray(new CompletableFuture[futures.size()]); // Wait for all CompletableFuture.allOf(completable).join(); } } 
0
source

All Articles