2012-04-26 20 views
6

Tôi muốn sử dụng hai đối sánh tùy chỉnh cho một phương thức. Về cơ bản, nếu tôi vượt qua phương thức VALUE_A, tôi muốn nó trả về RESULT_A, và nếu tôi vượt qua nó VALUE_B, tôi muốn nó trả về RESULT_B. Vì vậy, đây là một mã số trích đoạn:Mockito hoạt động lạ khi tôi gán nhiều đối sánh tùy chỉnh cho một phương thức đơn lẻ

class IsNonEmpty extends ArgumentMatcher<Get> { 
    public boolean matches(Object get) { 
     //For some reason, this method is called when I assign the IsEmpty matcher to MockHtable.get() 
     //When this happens, the value of the get argument is null, so this method throws an NPE 

     return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)); 
    } 
} 

class IsEmpty extends ArgumentMatcher<Get> { 
    public boolean matches(Object get) { 
     return !(Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key))); 
    } 
}  

[...] 

//This line executes just fine 
Mockito.when(mockHTable.get(Mockito.argThat(new IsNonEmpty()))).thenReturn(dbResult); 

[...] 

//This line calls IsNonEmpty.matches() for some reason. IsNonEmpty.matches() throws an NPE 
Mockito.when(mockHTable.get(Mockito.argThat(new IsEmpty()))).thenReturn(emptyResult); 

Khi tôi giao cho tùy chỉnh khớp IsEmpty phương pháp mockHTable.get(), nó gọi là IsNonEmpty.matches() chức năng. Không có ý tưởng tại sao nó làm điều này. Vì vậy, tôi thay đổi lớp IsNonEmpty thành lớp này:

class IsNonEmpty extends ArgumentMatcher<Get> { 
    public boolean matches(Object get) { 
     //For some reason, this method is called when I assign the IsEmpty matcher. Weird, no? 
     if(get == null) { 
      return false; 
     } 

     return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)); 
    } 
} 

và sau đó mọi thứ hoạt động tốt! IsNonEmpty.matches() vẫn được gọi khi tôi gán đối sánh IsEmpty với hàm mockHTable.get(), nhưng các trình đối sánh của tôi hoạt động chính xác như thế nào.

Vậy thỏa thuận là gì? Lý do tại sao điều này xảy ra? Là công việc của tôi xung quanh một cách đầy đủ để bù đắp cho hành vi kỳ quặc này, hoặc tôi làm điều đó sai?

Trả lời

11

Lý do tại sao IsNonEmpty.matches() được gọi là trên dòng thứ hai của stubbing là Mockito.argThat(new IsEmpty()) trả về null, sau đó được chuyển đến mockHTable.get(). Cuộc gọi này phải được kiểm tra so với trước đó, để xem nó có phù hợp hay không; và điều đó có nghĩa là gọi số IsNonEmpty.matches().

Tôi không chắc chắn tại sao điều này làm cho thử nghiệm của bạn thất bại - thật khó để nói mà không nhìn thấy tất cả mã.

Nhưng, tôi thực sự khuyên bạn nên sử dụng doReturn...when thay vì when...thenReturn bất cứ khi nào bạn phải lập cùng một mô hình nhiều lần. Bạn sẽ không gặp phải vấn đề như thế này nếu bạn làm thế. Trên thực tế, tôi thích sử dụng doReturn...when tùy chọn when...thenReturn luôn (và tương tự doThrowdoAnswer), mặc dù hầu hết mọi người thích when...thenReturn.

Viết lại một trong các đường thẳng của bạn với cú pháp doReturn...when giống như sau. Khác là tương tự.

Mockito.doReturn(dbResult).when(mockHTable).get(Mockito.argThat(new IsNonEmpty())); 

Cuối cùng, lời cầu xin, thay mặt cho nhóm phát triển Mockito (mà tôi là thành viên). Nếu bạn nghĩ rằng đó là một lỗi trong Mockito ở đây - và từ mô tả của bạn, tôi nghĩ rằng cũng có thể - Vui lòng

  • gửi một thông điệp tới các nhóm gửi thư Mockito ([email protected]) HOẶC
  • nêu một vấn đề về danh sách các vấn đề về Mockito (http://code.google.com/p/mockito/issues/list).

Điều này rất hữu ích cho nhóm Mockito nếu bạn thực sự có thể đăng một ví dụ hoàn chỉnh, thay vì chỉ là những gì bạn nghĩ là - đôi khi nguyên nhân của vấn đề Mockito ở một nơi khá bất ngờ.

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