9

カウントダウンラッチを使用して同期メソッドに変換している非同期メソッドがあります。mockitoのタイムアウト関数を使用せずに単体テストを作成するのに苦労しています。非同期メソッドの呼び出しを待機するようにverifyメソッドを取得する方法を理解できません:

public interface SyncExchangeService {
    boolean placeOrder(Order order);
}
public interface ExchangeService {
    void placeOrder(Order order, OrderCallback orderResponseCallback);
}

public interface OrderCallback {
    public void onSuccess();
    public void onFailure();
}



public class SyncExchangeServiceAdapter implements SyncExchangeService {
    private ExchangeService exchangeService;

    public SyncExchangeServiceAdapter(ExchangeService exchangeService) {
        this.exchangeService = exchangeService;
    }

    @Override
    public boolean placeOrder(Order order) {

        final CountDownLatch countdownLatch=new CountDownLatch(1);
        final AtomicBoolean result=new AtomicBoolean();
        exchangeService.placeOrder(order, new OrderCallback() {

            @Override
            public void onSuccess() {
                result.set(true);
                countdownLatch.countDown();
            }

            @Override
            public void onFailure(String rejectReason) {
                result.set(false);
                countdownLatch.countDown();
            }
        });
        try {
            countdownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return result.get();
    }
}


public class SyncExchangeServiceAdapterTest {
    private ExchangeService mockExchange=mock(ExchangeService.class);
    private SyncExchangeServiceAdapter adapter=new SyncExchangeServiceAdapter(mockExchange);
    private Boolean response;
    private ArgumentCaptor<Boolean> callback=CaptorArgumentCaptor.forClass(OrderCallback.class);
    private CountDownLatch latch=new CountDownLatch(1);


    @Test
    public void testPlaceOrderWithSuccess() throws Exception {
        final Order order=mock(Order.class);
         Executors.newSingleThreadExecutor().submit(new Runnable() {
            @Override
            public void run() {
                response=adapter.placeOrder(order);
                latch.countDown();
            }
        });
            verify(mockExchange,timeout(10) ).placeOrder(eq(order), callbackCaptor.capture());
//the timeout method is not really recommended and could also fail randomly if the thread takes more than 10ms


        callbackCaptor.getValue().onSuccess();
        latch.await(1000,TimeUnit.MILLISECONDS);
            assertEquals(true,response);
    }


}
4

2 に答える 2

3

これらの種類のテストでは、awaitilityと呼ばれる小さなライブラリを使用するのが好きです。カウントダウンラッチを使用して自分で行うこともできますが、これまで見てきたように、それを機能させるには、マチェーテでテストをハックする必要があります。

このテストでは、ラッチを待った後で検証を呼び出す必要があります。

コードのもう1つの問題は、private Boolean responseです。別のスレッドで変更しているので、それを作成するAtomicBooleanか、少なくとも宣言する必要がありvolatileます。

于 2012-07-23T04:53:06.027 に答える
-1

私はあなたを正しく理解しているかどうかわかりません。あるスレッドが他のスレッドが何かをするまで無期限に待機することをテストしたい場合、私はあなたがそれを行うことができないと言うでしょう。これは、プログラムが終了するかどうかを尋ねていることを意味します。代わりに、2つのことができます。

  1. 定期的な同時テストを実行します(定義上、ランダムであり、コードが正しいことを確認できません)。ロックを使用してサービスをシミュレートし、yeld()メソッドを使用する2つのスレッドで複雑なテストを作成します。クリティカルセクションでは、間違った順序がないかどうかをテストできます。もちろん、何度も実行する必要があるため、10ミリ秒以上かかります
  2. CountDownLatchが正しく機能すると想定し、それをモックして、その関数が正しい順序で呼び出されているかどうかを確認します
于 2012-06-20T20:03:36.453 に答える