import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import java.lang.reflect.Method;
import org.junit.Test;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MockitoSpyTest {
@Test
public void execTest() {
System.out.println("*** TEST 1 ***");
System.out.println("Test on unmodified object");
MySet ms = new MySetImpl();
ms.set("test value");
System.out.println("Set contains: " + ms.get());
// decorate ms1 with easymock
System.out.println("\n*** TEST 2 ***");
MySet spyMs = spy(ms);
doThrow(new NullPointerException("my test nullpointer")).when(spyMs).get();
System.out.println("Test decorated object with SPY");
spyMs.set("test value");
try {
System.out.println("Set contains: " + spyMs.get());
} catch (NullPointerException e) {
System.out.println("NullPointerException - as expected");
}
// Enhance call with CGLIB
System.out.println("\n*** TEST 3 ***");
System.out.println("Test on CGLIB decorated object");
Enhancer enc = new Enhancer();
enc.setSuperclass(MySetImpl.class);
enc.setInterfaces(new Class[] { MySet.class });
enc.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if ("get".equals(method.getName())) {
System.out.println("CGLIB decorated GET call");
}
return proxy.invokeSuper(obj, args);
}
});
MySet ms1 = (MySet) enc.create();
ms1.set("test value");
System.out.println("Set contains: " + ms1.get());
// decorate ms1 with easymock
System.out.println("\n*** TEST 4 ***");
System.out.println("Test on CGLIB decorated object with SPY");
MySet spyMs1 = spy(ms1);
doThrow(new NullPointerException("my test nullpointer")).when(spyMs1).get();
spyMs1.set("test value");
System.out.println("Set contains: " + spyMs1.get());
}
public interface MySet {
void set(String val);
String get();
}
public static class MySetImpl implements MySet {
String val;
public void set(String val) {
this.val = val;
System.out.println("Original SET call:" + val);
}
public String get() {
System.out.println("Original GET call:" + val);
return val;
}
}
}
Ví dụ trên sản lượng sản xuất:
*** TEST 1 ***
Test on unmodified object
Original SET call:test value
Original GET call:test value
Set contains: test value
*** TEST 2 ***
Test decorated object with SPY
Original SET call:test value
NullPointerException - as expected
*** TEST 3 ***
Test on CGLIB decorated object
Original SET call:test value
CGLIB decorated GET call
Original GET call:test value
Set contains: test value
*** TEST 4 ***
Test on CGLIB decorated object with SPY
CGLIB decorated GET call
Original GET call:test value
Original SET call:test value
CGLIB decorated GET call
Original GET call:test value
Set contains: test value
Bây giờ TEST 2
và TEST 4
nên ném NullPointerException
trên get
cuộc gọi - dựa trên gián điệp Mockito: doThrow(new NullPointerException("my test nullpointer")).when(spyMs1).get();
Các "TEST 4" không ném dự kiến ngoại lệ bởi vì nó đã được trang trí với CGLIB - chúng ta cũng có thể thấy trên bàn điều khiển gọi CGLIb đang được thực hiện: GLIB decorated GET call
và không gọi vào đối tượng gián điệp. Hiệu ứng tương tự có thể đạt được khi sử dụng Spring AOP với các proxy CGLIB.
Nguồn
2012-02-08 16:28:13
Có vẻ như đây thực sự chỉ là cú pháp của mockito, sử dụng trình tạo mẫu. (giống như rất nhiều mocking-frameworks khác) –
Theo như tôi biết Mockito, mã của bạn là chính xác. Tài liệu cho biết 'doThrow' chỉ dành cho các phương thức void, vì vậy bạn có thể thử lại với ví dụ: 'clear()' để xem đây có phải là vấn đề không. Nhưng tôi không thể tưởng tượng tại sao 'doThrow' không hoạt động trên các phương thức không trống như' doReturn'. – flyx
Không chắc chắn những gì bạn đang yêu cầu ở đây. Có, bạn có thể sử dụng doThrow(), ngay cả đối với các phương thức không có giá trị. Lý do tại sao các tài liệu đề cập đến phương pháp void là bởi vì có một cú pháp thứ hai cho ném stubbing, mà không làm việc cho các phương pháp void, và được trình bày trước khi doThrow một trong các tài liệu. Nhận được (0) trong ví dụ của bạn chỉ được gọi là gián điệp, không phải là Danh sách thực. Các gián điệp biết rằng đó là trong bối cảnh của một doThrow, vì vậy thay vì gọi REAL nhận được (0), nó stubs nó thay thế. Đó là những gì bạn đang yêu cầu? Nếu vậy, tôi sẽ biến nhận xét này thành câu trả lời. –