2011-06-23 34 views
6

Tôi đang học Mockito vào lúc này và một trong những điều tôi đang làm để củng cố việc học của mình là chuyển đổi một bài kiểm tra JUnit cũ bằng cách sử dụng một lớp mô hình được sử dụng để thay thế Mockito. Tuy nhiên, tôi đã chạy vào một tình huống mà tôi không chắc chắn làm thế nào để xử lý.Có thể truy vấn đối số được truyền cho đối tượng giả lập Mockito không?

Cụ thể, đơn vị của tôi đang thử nghiệm xây dựng một String được chuyển đến đối tượng được giả dạng làm tham số trong một cuộc gọi phương thức trên đó. Tôi muốn kiểm tra rằng String được xây dựng chính xác. Thách thức là một phần của String là một khóa băm được tạo ra trong nội bộ và thay đổi về mọi yêu cầu. Một giải pháp có thể hoạt động sẽ là tạo ra thế hệ băm dưới sự kiểm soát của tôi và tiêm một trình tạo giả để thực thi thử nghiệm. Tuy nhiên, đây là một chút công bằng.

Lớp mô phỏng cuộn cũ của tôi sẽ lưu trữ các đối số được truyền cho nó mà tôi có thể truy vấn trong bài kiểm tra của mình. Điều này cho phép tôi truy vấn bắt đầu và kết thúc của số String thông qua các mục sau:

assertTrue(mockFtpClient.getFilePathAndName().startsWith("/data/inbound/XJSLGG.")); 
assertTrue(mockFtpClient.getFilePathAndName().endsWith(".pdf")); 

Đây là một thử nghiệm đủ hiệu quả cho khẩu vị của tôi. Vì vậy, câu hỏi của tôi là, là nó có thể sử dụng Mockito để truy vấn hoặc có được một tổ chức của các đối số thông qua một phương pháp để tôi có thể thực hiện một cái gì đó tương tự như trên?

CẬP NHẬT 24/06/2011: Tại thời điểm này tôi đã ngoại trừ câu trả lời của Gnon. Tuy nhiên, tôi đã phát hiện ra một cái gì đó hoạt động tốt hơn cho tôi. Cụ thể là ArgumentCaptor. Dưới đây là cách hoạt động:

ArgumentCaptor<String> fileNameArgument = ArgumentCaptor.forClass(String.class); 
verify(mockFtpClient).putFileOnServer(fileNameArgument.capture()); 
assertTrue(fileNameArgument.getValue().startsWith(START_FILE_NAME) && 
      fileNameArgument.getValue().endsWith(END_FILE_NAME)); 

Các javadoc cho nhà nước Mockito rằng ArgumentCaptor nói chung là một lựa chọn tốt hơn khi bạn có một yêu cầu phù hợp với lập luận cụ thể một lần, như tôi đã làm ở đây.

+1

Cảm ơn bạn đã cập nhật, tôi không biết về ArgumentCaptor. –

+0

ArgumentCaptor sẽ thay đổi cuộc sống (mã hóa) của tôi! –

Trả lời

3

Về cơ bản bạn cần phải sử dụng argThat() trong Mockito, cho phép bạn đối xử với một hamcrest Matcher như một lập luận xác minh. Đây là mã bạn sử dụng để thực hiện các xác nhận tùy chỉnh về một đối số được chuyển vào:

@Test 
public void testname() throws Exception { 
    HashReceiver receiver = mock(HashReceiver.class); 
    receiver.set("hash"); 
    verify(receiver).set(argThat(new HashMatcher())); 
} 

class HashMatcher extends BaseMatcher<String> { 
    @Override 
    public boolean matches(Object item) { 
     String hash = (String) item; 
     if (hash.startsWith("/data/inbound/XJSLGG.") && hash.endsWith(".pdf")) 
      return true; 
     return false; 
    } 
} 

// Mocked 
class HashReceiver { 
    public void set(String hash) { 
    } 
} 

Bạn có thể sử dụng đối sánh chung thay thế hoặc kết hợp các đối sánh chung chung.

+0

Cảm ơn Gnon, tôi nghĩ rằng giải pháp này hoạt động thực sự tốt cho những gì tôi cần. Xấu hổ quá nhiều mã của nó, nhưng sau đó đây không phải là một kịch bản phổ biến. –

+0

Đây là nơi bạn sẽ tìm thấy phương thức argThat(): http://docs.mockito.googlecode.com/hg/latest/org/mockito/Matchers.html#argThat(org.hamcrest.Matcher). Quá trình nhập của bạn phải là 'nhập static org.mockito.Matchers.argThat;' –

1

Hãy xem câu trả lời được chấp nhận cho câu hỏi này mockito-how-to-make-a-method-return-an-argument-that-was-passed-to-it nó sẽ chỉ cho bạn cách giữ một đối số được chuyển đến lời gọi phương thức giả của bạn.

+0

Không tệ, nhưng việc sử dụng đối tượng Trả lời để giữ một tham số đầu vào có vẻ hơi lạc hậu với tôi và tôi không hoàn toàn chắc chắn rằng nó sẽ hoạt động với chữ ký phương thức void của tôi. Cảm ơn mặc dù! Tôi không biết về câu trả lời trước đó. –

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