假设我有这样一个方法:
synchronized void incrementIndex() {
index++;
}
如果多个线程同时尝试增加索引,我想对该方法进行单元测试以查看索引的最终值是否设置正确。假设我不知道方法声明中的“synchronized”关键字(而且我只知道方法的契约),我该如何进行测试?
附注如果有帮助,我正在使用 Mockito 编写测试用例。
最佳答案
您可以通过让多个线程执行该方法然后断言结果符合您的预期来对此进行测试。我怀疑这会有多有效和可靠。众所周知,多线程代码难以测试,这主要归结为仔细的设计。我肯定会建议添加测试,断言您期望通过 synchronized 实现的方法实际上具有 synchronized 修饰符。请参阅以下两种方法的示例:
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;
}
}
}
关于java - 如何对同步方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26967036/