2012-06-19 5 views
8

Tôi có một phương thức không đồng bộ mà tôi đang chuyển sang phương thức đồng bộ hóa bằng cách sử dụng chốt đếm ngược. Tôi đang đấu tranh với việc viết một bài kiểm tra đơn vị mà không cần sử dụng chức năng hết thời gian của mockito. Tôi không thể tìm ra phương pháp xác minh để chờ cuộc gọi phương thức không đồng bộ:Mockito với Java async-> công cụ đồng bộ hóa

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


} 

Trả lời

2

Đối với những loại xét nghiệm Tôi thích sử dụng một thư viện nhỏ có tên là awaitility. Bạn có thể tự mình làm với một chốt đếm ngược, nhưng như bạn đã thấy bạn phải hack lên thử nghiệm của bạn với một dao rựa để làm cho công việc đó.

Trong thử nghiệm này, bạn nên gọi xác minh sau khi bạn đã đợi chốt.

Một vấn đề khác trong mã của bạn là private Boolean response. Vì bạn đang thay đổi nó trong một chủ đề khác, bạn nên thực hiện một số AtomicBoolean hoặc ít nhất khai báo nó volatile.

+1

+1 cho sự chờ đợi. Tôi chưa bao giờ nghe về nó, nhưng có vẻ khá hữu ích. – jhericks

-1

Tôi không chắc là tôi hiểu chính xác bạn. nếu bạn muốn kiểm tra xem một luồng có chờ đợi vô thời hạn cho đến khi luồng khác thực hiện điều gì đó không thì tôi sẽ nói bạn không thể làm được. bởi vì điều đó có nghĩa là bạn đang hỏi liệu chương trình có kết thúc hay không. thay vào đó bạn có thể làm hai việc.

  1. thực hiện các kiểm tra đồng thời thường xuyên (theo định nghĩa là ngẫu nhiên và không cho bạn chắc chắn mã đúng). bạn tạo thử nghiệm phức tạp với hai luồng sử dụng khóa và mô phỏng dịch vụ và sử dụng phương thức yeld(). trong các phần quan trọng bạn có thể kiểm tra nếu không có thứ tự không chính xác. tất nhiên bạn phải chạy nó nhiều lần vì vậy nó sẽ đưa bạn hơn 10ms
  2. rằng CountDownLatch hoạt động chính xác, châm biếm nó và kiểm tra xem chức năng của nó được gọi theo thứ tự đúng
+0

Tôi không chắc chắn những gì bạn đang nhận được tại .. Tôi đang tìm cách xác định để kiểm tra lớp ở trên. tức là nó sẽ LUÔN mang lại kết quả tương tự bất kể bạn chạy nó một lần hay một triệu lần. Tại thời điểm này có một điều kiện chủng tộc để nó có thể thất bại. –

+0

Cũng không cần phải cấu trúc lại lớp, bạn không thể giả lập CountDownLatch vì nó không được truyền vào như một phụ thuộc. –

+0

đó là quan điểm của tôi. bạn chỉ đơn giản là không thể kiểm tra mã đa luồng theo cách xác định để nói: 'nó là chính xác'. bạn không thể kiểm tra xem một luồng có chờ đến [http://en.wikipedia.org/wiki/Halting_problem] khác không. và tất nhiên bạn có thể giả định countDownLatch, xem powermock và whitebox – piotrek