2011-10-29 40 views
12

Giả sử tôi có một đối tượng giả, và tôi không muốn khai phá bất kỳ phương thức nào, nhưng tôi muốn tạo phương thức của đối tượng nó trở lại. Ví dụ,Mockito - Đặt một phương thức của đối tượng được trả về bằng phương thức đối tượng giả

when(mockObject.method1()).thenReturn(returnValue) 

là cách nó thường được thực hiện, nhưng tôi đang tìm,

when(mockObject.method1().method2()).thenReturn(returnValue) 

Là có thể? Tôi nhận được một NullPointerException nếu tôi làm điều đó. Hiện tại tôi đã khai báo phương thức đầu tiên để trả về một đối tượng giả, và sau đó sử dụng đối tượng giả đó trả về, khai báo phương thức thứ hai. Tuy nhiên, những đối tượng giả tạm thời này vô dụng đối với tôi và sau khi kết hợp nhiều phương thức với nhau, điều đó dẫn đến rất nhiều đối tượng giả tạo vô ích.

EDIT: Trên thực tế, có thể chuỗi hoạt động, nhưng đối tượng của tôi đang gây ra lỗi NPE. Mã này (dòng đầu tiên) đang gây ra một NPE:

when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer); 
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer); 

Nhưng mã này hoạt động:

IndexManager indexManager = mock(IndexManager.class); 
when(graphDb.index()).thenReturn(indexManager); 
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer); 
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer); 

Vì vậy chaining được kết không làm việc cho getNodeAutoIndexer() trả về một đối tượng AutoIndexer trong khi nó làm việc cho getRelationshipAutoIndexer() trả về một RelationshipAutoIndexer. Cả hai giá trị trả về đều được mô phỏng như sau:

nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class); 
relAutoIndexer = mock(RelationshipAutoIndexer.class); 

Vậy điều gì có thể gây ra sự cố?

Trả lời

13

Không có vấn đề gì cả.

Hãy kiểm tra những 4 dòng mã:

IndexManager indexManager = mock(IndexManager.class); 
when(graphDb.index()).thenReturn(indexManager); 
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer); 
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer); 

Dòng đầu tiên tạo ra một indexManager giả.

Điều thứ hai yêu cầu biểu đồ giả lập trả về indexManager (mô phỏng được tạo ở dòng đầu tiên) khi phương thức chỉ mục được gọi.

Phương thức thứ ba là chỉ số mô phỏngManager (được tạo ở dòng đầu tiên) để trả về nodeAutoIndexer khi phương thức getNodeAutoIndexer của nó được gọi.

Và dòng cuối cùng gọi graphDb.index(), trả về chỉ số giả lập (bạn đã yêu cầu nó làm điều đó ở dòng hai) và hỏi indexManager này (đó là mô hình bạn tạo ở dòng đầu tiên) để trả về relAutoIndexer khi phương thức getRelationshipAutoIndexer của nó được gọi.

Dòng cuối cùng chỉ hoạt động vì bạn đã nói với biểu đồ giảDB gì cần trả về khi phương thức chỉ mục của nó được gọi. Nếu bạn chưa làm điều này trước đây, phương thức graphDb.index() giả định sẽ trả về null và bạn sẽ có một NPE.

+1

Cảm ơn. Vì vậy, chúng ta hãy nói rằng tôi có một chuỗi dài các chức năng, tôi sẽ phải lặp lại quá trình này của stubbing mỗi chức năng? Không có cách nào để nhận được mã cho phép NPE hoạt động mà không có chỉ mục stubbing()? Tôi cảm thấy như Mockito bằng cách nào đó sẽ tự động stub những phương pháp với các đối tượng giả dựa trên các loại trở lại của các chức năng để tôi không phải bận tâm chức năng stubbing tôi không cần trực tiếp. Tôi chỉ cần những chức năng đó để có được các chức năng khác ... – gsingh2011

+1

No. Giá trị trả về mặc định là null cho các phương thức trả về các đối tượng. IMHO, vấn đề bạn đang gặp phải là dấu hiệu cho thấy bạn vi phạm luật Demeter: đừng nói chuyện với người lạ. –

+4

Lưu ý rằng mockito cung cấp tính năng sơ khai sâu ('mock (LegacyType).class, RETURNS_DEEP_STUBS) '), nhưng ngăn cản việc sử dụng nó bởi vì bạn có thể phá vỡ các luật thiết kế _good_, chẳng hạn như Luật Demeter. Cũng xin lưu ý rằng tính năng này không hoạt động với các loại chung chung, ví dụ như Danh sách. – Brice

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