Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to unit test a synchronized method?

Say I have such a method:

synchronized void incrementIndex() {
      index++;
}

I want to unit test this method to see whether index's final value is set correctly if multiple threads simultaneously attempt to increment index. Assuming I don't know about the "synchronized" keyword in the method's declaration (and I only know the contract of the method), how can I do the test?

p.s. I am using Mockito for writing test cases if it helps.

like image 552
elfar Avatar asked Nov 17 '14 06:11

elfar


People also ask

How do we synchronize the test method in JUnit?

Instructions: #1 - RunSynchronize JUnit Tests once to create the @Testable annotation. #2 - Annotate desired source methods with @Testable annotation. #3 - Run Synchronize JUnit Tests to create test methods.

Can we use synchronized with static?

Static Synchronized method is also a method of synchronizing a method in java such that no two threads can act simultaneously static upon the synchronized method. The only difference is by using Static Synchronized.

What happens when synchronized method is called?

When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.

How do you test a thread?

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.


1 Answers

You could test this by having multiple threads execute the method and then asserting that the result is what you would expect. I have my doubts about how effective and reliable this would be. Multithreaded code is notoriously difficult to test and it mostly comes down to careful design. I would definitely recommend adding tests that assert that the methods you expect to by synchronized actually have the synchronized modifier. See an example of both approaches below:

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

public class SyncTest {
  private final static int NUM_THREADS = 10;
  private final static int NUM_ITERATIONS = 1000;

  @Test
  public void testSynchronized() throws InterruptedException {
    // This test will likely perform differently on different platforms.
    ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
    final Counter sync = new Counter();
    final Counter notSync = new Counter();

    for (int i = 0; i < NUM_THREADS; i++) {
      executor.submit(new Runnable() {
        @Override
        public void run() {
          for (int i = 0; i < NUM_ITERATIONS; i++) {
            sync.incSync();
            notSync.inc();
          }
        }
      });
    }

    executor.shutdown();
    executor.awaitTermination(5, TimeUnit.SECONDS);
    assertThat(sync.getValue(), is(NUM_THREADS * NUM_ITERATIONS));
    assertThat(notSync.getValue(), is(not(NUM_THREADS * NUM_ITERATIONS)));
  }

  @Test
  public void methodIncSyncHasSynchronizedModifier() throws Exception {
    Method m = Counter.class.getMethod("incSync");
    assertThat(Modifier.isSynchronized(m.getModifiers()), is(true)); 
  }

  private static class Counter {
    private int value = 0;

    public synchronized void incSync() {
      value++;
    }

    public void inc() {
      value++;
    }

    public int getValue() {
      return value;
    }
  }
}
like image 51
LeffeBrune Avatar answered Oct 03 '22 10:10

LeffeBrune