2014-12-07 16 views
5

Tôi thường làm việc với các phương thức chấp nhận gọi lại và gọi lại có vẻ khó kiểm tra. Chúng ta hãy xem xét kịch bản sau đây, nếu có một phương thức chấp nhận gọi lại với một phương thức đơn (để đơn giản, tôi giả định phương thức thử nghiệm là đồng bộ), bảng sau có thể được viết chỉ để đảm bảo rằng phương thức gọi lại được gọi:Thử nghiệm đơn vị Java: cách dễ nhất để kiểm tra xem một cuộc gọi lại có được gọi là

@Test 
public void testMethod() { 
    final boolean[] passed = {false}; 
    method(new Callback() { 
     @Override 
     public void handle(boolean isSuccessful) { 
      passed[0] = isSuccessful; 
     } 
    }); 
    assertTrue(passed[0]); 
} 

Dường như đại diện. Tôi muốn biết: là có một cách thanh lịch hơn để kiểm tra mã như vậy để làm cho mã ở trên trông giống như mã giả bên dưới?

@Test 
public void testMethod() { 
    // nothing explicit here, implicit boolean state provided by a test-runner 
    method(new Callback() { 
     @Override 
     public void handle(boolean isSuccessful) { 
      if (isSuccessful) { 
       pass(); // not sure how it should look like: 
         // * an inherited method that sets the state to "true" 
         // * or an object with the pass method 
         // * whatever 
         // but doesn't exit testMethod(), just sets the state 
      } 
     } 
    }); 
    // nothing explicit here too: 
    // test runner might check if the state is changed to true 
    // otherwise an AssertionError might be thrown at the end of the method implicitly 
} 

Làm sạch một chút. Có thể nào trong JUnit, TestNG hoặc bất kỳ khung kiểm thử nào khác không? Cảm ơn!


CẬP NHẬT

Xin lỗi, tôi dường như đã hỏi một câu hỏi mơ hồ mà không thực sự đáp ứng những gì tôi muốn hỏi. Về cơ bản, tôi có nghĩa là bất kỳ mã nào (không nhất thiết phải gọi lại) có thể được gọi nếu một số điều kiện nhất định chỉ được thỏa mãn để đặt trạng thái kết quả thành đúng. Nói một cách đơn giản, tôi chỉ muốn loại bỏ số boolean[] passed ban đầu và số assertTrue(passed[0]) cuối cùng giả định rằng chúng là một dạng mở đầu và phần kết thúc tương ứng và giả sử rằng trạng thái ban đầu được đặt thành false do đó cần gọi hàm pass() để đặt trạng thái là true . Không có vấn đề cách các passed[0] được đặt thành true, bất kể từ đâu. Nhưng tiếc là tôi đã hỏi câu hỏi này bằng ngữ cảnh gọi lại, tuy nhiên đây chỉ là một lựa chọn, không phải là một yêu cầu. Vì vậy, tiêu đề của câu hỏi không phản ánh những gì tôi thực sự muốn hỏi, nhưng trước khi cập nhật một số câu trả lời đã được đăng.

Trả lời

8

Điều này thường là điều mà một khung làm việc giả có thể làm cho bạn.

Với Mockito ví dụ:

// imports ommited for brevity 
@Test 
public void callbackIsCalled() 
{ 
    final CallBack callBack = mock(CallBack.class); 
    method(callBack); 

    verify(callBack, only()).handle(any()); 
} 

Tất nhiên, đây là một ví dụ về chế độ xác minh (only()) và giá trị khớp (any()). Bạn có thể làm nhiều hơn nữa ...

(khuôn khổ chế giễu khác tồn tại, nhưng cá nhân tôi thấy Mockito dễ sử dụng nhất, ngoài việc là một trong những mạnh nhất)

+0

Cảm ơn câu trả lời! Có, Mockito là một lib thực sự tốt đẹp. Thành thật mà nói, tôi đã không đưa các thư viện mocking vào tài khoản: Tôi chỉ muốn loại bỏ lá cờ thay thế và các xác nhận sau. Với Mockito, 'verify' phải được gọi đúng cách. Tôi chỉ nghĩ rằng khẳng định cuối cùng có thể là ngầm định và "được cung cấp" bởi người thử nghiệm. –

+0

Vâng, như tôi đã nói, nó chỉ là một giá trị phù hợp; nếu bạn muốn, bạn có thể thay thế đối số bằng 'true' hoặc thậm chí là' ArgumentCaptor '. – fge

+0

Tại sao lại là downvote? – fge

7

Cho rằng đây là loại điều bạn 'tái khả năng cần ở một số nơi, tôi sẽ chỉ tạo ra một lớp tên là để sử dụng cho các bài kiểm tra:

public class FakeCallback implements Callback { 
    private boolean wasSuccessful; 
    private boolean handleCalled; 

    @Override public void handle(boolean isSuccessful) { 
     this.wasSuccessful = isSuccessful; 
     handleCalled = true; 
    } 

    // Getters for fields above 
} 

sau đó bạn có thể sử dụng một cái gì đó như:

// Arrange... 
FakeCallback callback = new FakeCallback(); 

// Act... 
method(callback); 

// Assert 
assertTrue(callback.wasHandleCalled()); 
assertTrue(callback.wasSuccessful()); 

Bạn có thể hoàn toàn sử dụng một khuôn khổ mocking cho điều này thay vào đó, nhưng cá nhân tôi thấy rằng nó thường đơn giản hơn để tạo ra một thực hiện giả đơn hơn thiết lập mocks nhiều lần. Cả hai cách sẽ làm việc mặc dù.

+0

Cảm ơn câu trả lời. Tôi cũng nghĩ về ý tưởng loại bỏ các xác nhận sau (đây cũng là một phần của câu hỏi mơ hồ), nhưng tôi không chắc đó có phải là một ý hay hay không. –

+0

@LyubomyrShaydariv: Bạn đang cố kiểm tra cái gì? Nếu bạn không quan tâm liệu cuộc gọi lại có được gọi hay không, hoặc đối số là gì, thì bạn có thể dễ dàng thực hiện nó ... –

1
danh sách

Hãy cho :: thêm bao callback

Khi nhiệm vụ này là để thử nghiệm một callback đó là một giao diện chức năng chấp nhận một tham số (ở đây một boolean, cũng có thể là String hoặc bất kỳ loại ngẫu nhiên), có vẻ như hầu hết súc tích để chuẩn bị một danh sách, vượt qua các phương pháp List.add(e) như gọi lại và sau đó kiểm tra các nội dung của danh sách:

List<Boolean> callbackArgs = new ArrayList<>(); 
methodUnderTest(callbackArgs::add); 
// assert that the callback was called exactly once and with a "true" value: 
assertEquals(Arrays.asList(true), callbackArgs); 

trường hợp thay thế cho một callback chấp nhận Strings:

List<String> callbackArgs = new ArrayList<>(); 
methodUnderTest(callbackArgs::add); 
// assert that the callback was called twice with "foo" and "bar" values respectively: 
assertEquals(Arrays.asList("foo", "bar"), callbackArgs); 

Tương tự, một lớp truy cập có thể phục vụ để thử nghiệm một cuộc gọi lại không chấp nhận tham số. Ở đây sử dụng AtomicInteger, vì đó dường như là lớp duy nhất giống như truy cập có sẵn trong libs chuẩn - không cần tính chất nguyên tử ở đây:

AtomicInteger callbackCounter = new AtomicInteger(); 
methodUnderTest(callbackCounter::incrementAndGet); 
// assert that the callback was called 5 times: 
assertEquals(5, callbackCounter.get()); 
+0

Chỉ tiêu đề giúp tôi nhận ra việc kiểm tra cuộc gọi lại dễ dàng như thế nào. Tôi có một lớp học chấp nhận tham số Người tiêu dùng . Đơn giản chỉ cần chuyển vào danh sách :: thêm khi người tiêu dùng thực hiện thử nghiệm dễ dàng hơn nhiều như bây giờ tôi chỉ có thể xác minh rằng kích thước của danh sách là những gì tôi mong đợi, thay vì làm một số điều kỳ lạ với mocks. Vì vậy, +1. – Chewtoy

Các vấn đề liên quan