2012-08-23 37 views
12

Tôi đang sử dụng Mockito để kiểm tra JUnit. Vì vậy, có một hạng A cho rằng được sử dụng từ mã tôi muốn thử nghiệm:Mockito: khi Phương pháp A.a được gọi thì thực hiện B.b

class A{ 

    public A(){} 

    public final String a(String x){ 
     return "A.a: " + x; 
    } 

} 

và tôi muốn thay thế A.a Phương pháp gọi với một lời gọi phương thức với các đối số giống nhau và cùng một loại giá trị trả về. Như bạn có thể thấy, nó không thể ghi đè lên phương thức a bằng cách mở rộng lớp vì nó là cuối cùng. Vì vậy, những gì tôi có bây giờ là một lớp B với phương pháp B.b:

class B{ 

    public B(){} 

    public String b(String x){ 
     return "B.b: " + x; 
    } 

} 

Bây giờ tôi muốn chắc chắn mỗi khi A.a được gọi là từ mã, giá trị trả về của B.b được sử dụng để thay thế. Có một khả năng để đạt được điều này với Mockito (một cái gì đó như Mockito.when(A.a(x)).thenReturn(B.b(x));) nhưng với cùng một tham số x, mà không biết giá trị của x?

Bất kỳ trợ giúp nào sẽ được đánh giá cao, cảm ơn bạn trước!

+2

Kịch bản bạn muốn thử nghiệm là gì? Tại sao A.a() là cuối cùng? và Tại sao bạn muốn thay thế cuộc gọi của A.a()? Từ những gì tôi hiểu bạn muốn ghi đè A.a(), phải không? – Adelin

+1

Tôi đang thử nghiệm một dự án Thư viện Android (tôi cũng sử dụng Robolectric để có thể thử nghiệm các dự án Android). Trong trường hợp cụ thể này tôi muốn thử nghiệm một cơ sở dữ liệu. Mã này gọi trình phân giải nội dung, nhà cung cấp nội dung được xác định trong AndroidManifest.xml và tôi không tìm thấy cách để đặt nhà cung cấp nội dung theo chương trình vì nó không được tải từ xml khi chạy thử nghiệm. Vì vậy, tôi muốn mã gọi nhà cung cấp nội dung thay vì trình giải quyết nội dung. – user1448982

Trả lời

4

Không thể ghi đè các phương thức cuối cùng cho các mock được tạo bởi Mockito, theo Mockito limits. Nhưng bạn có thể sử dụng Powermock để hack mã khi chạy để Mockito có thể thực hiện công việc của mình.

+2

Điều này xảy ra xung quanh vấn đề 'final' và câu trả lời của @ brice trả lời ý chính của câu hỏi ban đầu của bạn. – jhericks

18

Mockito mockito cũng hoạt động bằng cách mở rộng lớp và ghi đè phương thức, trong trường hợp của bạn là không thể trên A.a(String). Nếu bạn muốn điều này xảy ra, bạn phải loại bỏ công cụ sửa đổi cuối cùng.

Bây giờ giả sử A.a(String) không phải là cuối cùng, những gì bạn hỏi là hoàn toàn khả thi với Mockito:

given(mockA.a(anyString()).willAnswer(returnOfB(bInstance)); 

Answer<String> returnOfB(final B bInstance) { 
    return new Answer<String>() { 
     public String answer(Invocation invocation) { 
      String arg = (String) invocation.getActualArguments()[0]; 
      return bInstance.b(arg); 
     } 
    }; 
} 

Xin lưu ý câu trả lời này đã được viết trên một chiếc điện thoại và có thể có lỗi đánh máy, hoặc tên sai, mặc dù bạn sẽ nhận được ý tưởng về những gì nên được thực hiện để đạt được những gì bạn muốn.

Chúc mừng

+0

cảm ơn bạn, nhưng đó không phải là giải pháp cho tôi vì tôi không thể xóa công cụ sửa đổi cuối cùng. Đó là một số mã từ Android SDK. – user1448982

+3

@ sergej-zagursky có câu trả lời để giải quyết vấn đề sửa đổi cuối cùng, nhưng câu trả lời này là câu trả lời cho câu hỏi ban đầu của bạn. Đây là cách bạn đặt giá trị trả về của bạn trên giá trị 'x'. – jhericks

+0

Làm cách nào để nhập "đã cho"? – neves

1

Về cơ bản tôi đã thiết lập của bạn và đã viết Bài kiểm tra đơn vị với nó. Những gì xuất hiện trước là một thông báo lỗi đã tuyên bố rõ ràng điều này:

org.mockito.exceptions.misusing.MissingMethodInvocationException: khi() yêu cầu đối số phải là 'một cuộc gọi phương thức trên mô hình'.

Và sau đó trong dấu vết, nó nói rằng "bạn stub một trong hai phương thức: final/private/equals()/hashCode(). Các phương thức không thể được stubbed/verified".

Vì vậy, theo Mockito bạn không thể khai thác các phương thức cuối cùng, và đó là điều đó.

Chỉnh sửa: Vì vậy, bạn phải loại bỏ công cụ sửa đổi cuối cùng hoặc, trong trường hợp bạn bị mắc kẹt với lớp này như hiện tại, hãy tìm cách khác xung quanh nó.

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