2012-06-19 4 views
8

私は非同期メソッドを持っています。私はカウントダウンラッチを使って同期メソッドに変換しています。私はmockitoのタイムアウト機能を使わずに単体テストを書くのに苦労しています。私は、非同期メソッド呼び出しを待つことを確認する方法を取得する方法を考え出すことはできません。Java async-> sync converterを使用したMockito

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); 
    } 


} 

答えて

2

で呼び出されているかどうかを確認しています私はawaitilityという小さなライブラリを使いたい。あなたはカウントダウンラッチでそれを自分で行うことができますが、あなたが見たようにマチェッテを使ってテストをハックしてその作業を行わなければなりません。

このテストでは、ラッチを待ってからverifyを呼び出す必要があります。

コードのもう1つの問題はprivate Boolean responseです。別のスレッドで変更しているので、AtomicBooleanにするか、少なくともvolatileと宣言してください。

+1

+1を作成すると役に立つでしょう。私はそれについて聞いたことがないが、それは非常に有用に見える。 – jhericks

-1

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

  1. 定期的な並行テスト(定義上、ランダムであり、コードが正しいことを確信できません)。ロックを使用する2つのスレッドで複雑なテストを作成し、サービスをシミュレートし、yeld()メソッドを使用します。クリティカルセクションでは、誤った順序がないかどうかをテストできます。もちろん、あなたはそれを何度も実行することが表示されますので、10ms以上
  2. はそれを嘲笑、たCountDownLatchが正常に動作することを前提とし、その機能は、テストのこれらの種類のために右の順
+0

あなたは何を得ているのかよく分かりません。上記のクラスをテストする決定的な方法を探しています。すなわち、それを1回または100万回実行するかどうかにかかわらず、常に同じ結果が得られます。現時点では競合状態が存在するため、失敗する可能性があります。 –

+0

また、クラスを再構成することなく、CountDownLatchを依存関係として渡されないように模擬することはできません。 –

+0

それは私のポイントです。決定的な方法でマルチスレッドコードをテストすることはできません。「それは正しい」と言うだけです。あるスレッドが別のスレッド[http://en.wikipedia.org/wiki/Halting_problem]まで待つかどうかはテストできません。もちろん、あなたはcountDownLatchをモックすることができます。powermockとホワイトボックスを参照してください。 – piotrek

関連する問題