2013-04-11 36 views
40

Tôi đang sử dụng mockito 1.9.5. Tôi có đoạn mã sau:chế nhạo một phương thức trả lại Generics bằng ký tự đại diện bằng mockito

public class ClassA { 

public List<? extends MyInterface> getMyInterfaces() { 
    return null; 
} 

public static void testMock() { 
    List<MyInterface> interfaces = new ArrayList<>(); 
    ClassA classAMock = mock(ClassA.class); 
    when(classAMock.getMyInterfaces()).thenReturn(interfaces);  
} 

tôi nhận được một lỗi biên dịch cho thenReturn(interfaces) nói:

"The method thenReturn(List<capture#1-of ? extends MyInterface>) in the type 
OngoingStubbing<List<capture#1-of ? extends MyInterface>> is not applicable for the arguments 
(List<MyInterface>)" 

Tuy nhiên, khi tôi sử dụng phương pháp thenAnswer của Mockito, tôi không nhận được lỗi. Bất cứ ai có thể cho tôi biết những gì đang xảy ra? Tại sao tôi gặp lỗi khi sử dụng phương thức thenReturn? Có cách nào khác để giải quyết vấn đề này khi ClassA được cung cấp bởi bên thứ 3 và không thể sửa đổi được không?

+0

Bạn không nên có ký tự đại diện trong việc tái tạo lại 'getMyInterfaces'. Đó không phải là một thực hành tốt, bởi vì khách hàng của api đó phải đối phó với một ký tự đại diện mà họ không biết bất cứ điều gì về. – SpaceTrucker

+1

Tôi không kiểm soát API này. Nó được đưa ra bởi một bên thứ 3. – user1504992

+5

@SpaceTrucker Tôi nghĩ rằng có kiểu trả về như 'Danh sách 'là một điều hoàn toàn hợp lý để làm. Nó có nghĩa là bạn (là người gọi phương thức) có thể lấy các đối tượng 'MyInterface' ra khỏi danh sách, nhưng bạn không thể đặt bất cứ thứ gì vào đó. –

Trả lời

49

EDIT: Bắt đầu từ Mockito 1.10.x, các loại generics được nhúng trong lớp hiện đang được Mockito sử dụng cho mục đích sâu. I E.

public interface A<T extends Observer & Comparable<? super T>> { 
    List<? extends B> bList(); 
    T observer(); 
} 

B b = deep_stubbed.bList().iterator().next(); // returns a mock of B ; mockito remebers that A returns a List of B 
Observer o = deep_stubbed.observer(); // mockito can find that T super type is Observer 
Comparable<? super T> c = deep_stubbed.observer(); // or that T implements Comparable 

Mockito cố gắng hết sức mình để có được thông tin kiểu đó trình biên dịch nhúng, nhưng khi tẩy xoá được áp dụng, Mockito không thể làm bất cứ điều gì nhưng trả về một mô hình của Object.


gốc: Vâng đó là nhiều của một vấn đề với Generics hơn với Mockito. Đối với generics, bạn nên đọc những gì Angelika Langer đã viết trên chúng. Và đối với chủ đề hiện tại, ví dụ: ký tự đại diện, hãy đọc số section này.

Nhưng đối với ngắn, những gì bạn có thể sử dụng là cú pháp khác của Mockito để giúp đỡ với tình hình hiện tại của bạn:

doReturn(interfaces).when(classAMock).getMyInterfaces(); 

Hoặc với các bí danh BDD:

willReturn(interfaces).given(classAMock).getMyInterfaces(); 

Tuy nhiên, bạn có thể viết trình bao bọc thân thiện hơn. Điều đó sẽ giúp các nhà phát triển tương lai làm việc với cùng một API của bên thứ ba.


Lưu ý: bạn không nên giả mạo loại bạn không sở hữu, điều này có thể dẫn đến nhiều lỗi và vấn đề. Thay vào đó bạn nên có một số wrapper. DAO và kho lưu trữ ví dụ đại diện cho ý tưởng như vậy, người ta sẽ giả lập DAO hoặc giao diện kho lưu trữ, nhưng không phải là công cụ JDBC/JPA/hibernate. Có rất nhiều bài đăng trên blog về điều đó:

+0

Cảm ơn cũng vì các liên kết sâu sắc! – thSoft

+0

Cú pháp 'doReturn' không an toàn, mặc dù (bạn có thể trả về bất cứ thứ gì, không chỉ là danh sách thứ gì đó). (Mặc dù bạn nhận được một ngoại lệ vẫn còn trong quá trình thiết lập này - nhưng không phải nếu bạn đưa vào một loại danh sách khác.) –

+0

@ PaŭloEbermann Thật vậy, điều này là do loại xóa. Trong trường hợp này, kiểm tra được thực hiện trong thời gian chạy. Các hình thức khác có thể được loại kiểm tra tại thời gian biên dịch. – Brice

36

Một giải pháp (mặc dù ít có thể đọc được) là đủ điều kiện gọi phương thức tĩnh của when để ràng buộc ký tự đại diện:

Mockito.<List<? extends MyInterface>>when(classAMock.getMyInterfaces()).thenReturn(interfaces); 
+8

Đây là ma thuật đen, nhưng nó hoạt động hoàn hảo. Cảm ơn bạn –

+0

Đây là người duy nhất làm việc cho tôi. – gladed

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