ここで説明するシナリオでは、クラスjava.util.concurrent.CyclicBarrier
のインスタンスの使用をお勧めします - 非同期的に計算を行うスレッドの次の簡単な例を参照してください(ここでは、「パーセント完了」値を最初に50に設定し、 〜100)、 "%done"値をメインスレッドから取得できるようにします。 、私は私のSUT(あるいは、あなたのお気に入りのAOPフレームワークを使用することができます)の2つの計算方法を傍受するMockitoのスパイで、JUnitの4を使用
public class AsyncProcess implements Runnable {
private int percentageDone = 0;
public int getPercentageDone() { return percentageDone; }
public void doFirstHalf() { percentageDone = 50; }
public void doSecondHalf() { percentageDone = 100; }
public void run() {
doFirstHalf();
doSecondHalf();
}
}
ユニットテスト、これをするために:
はここでSUTクラスです。
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.doAnswer;
import java.util.concurrent.CyclicBarrier;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class AsyncProcessTest {
@Test
public void testExecute() throws Exception {
final CyclicBarrier firstHalfStarted = new CyclicBarrier(2);
final CyclicBarrier firstHalfFinished = new CyclicBarrier(2);
final CyclicBarrier secondHalfStarted = new CyclicBarrier(2);
final CyclicBarrier secondHalfFinished = new CyclicBarrier(2);
AsyncProcess process = Mockito.spy(new AsyncProcess());
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) throws Throwable {
firstHalfStarted.await();
invocation.callRealMethod();
firstHalfFinished.await();
return null;
}
}).when(process).doFirstHalf();
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) throws Throwable {
secondHalfStarted.await();
invocation.callRealMethod();
secondHalfFinished.await();
return null;
}
}).when(process).doSecondHalf();
new Thread(process, "AsyncProcess").start();
assertThat(process.getPercentageDone(), is(0));
firstHalfStarted.await();
firstHalfFinished.await();
assertThat(process.getPercentageDone(), is(50));
secondHalfStarted.await();
secondHalfFinished.await();
assertThat(process.getPercentageDone(), is(100));
}
}
このアプローチでは、関係するスレッドの実行フローをきめ細かく制御できます。 CyclicBarriersのペアをカプセル化し、インターセプトコールを抽出し、タイムアウトと適切な例外処理のサポートを抽出することで、「マイクロフレームワーク」に容易に拡張できます。
[Awaitility](https://github.com/awaitility/awaitility)と[ConcurrentUnit](https://github.com/jhalterman/concurrentunit)の2つのツールが役に立ちます。 – Jonathan