问题描述
想象一下以下代码:
List list = .....
List spy = spy(list);
doThrow(new NullpointerException()).when(spy).get(0);
doThrow(....)
执行 list.get(0)
- 这完全没有意义。我想定义模拟行为,而不是在这里调用方法.....我错过了什么?
doThrow(....)
executes list.get(0)
- this makes no sense at all. I would like to define mock behaviour and not to call a method here..... am I missing something?
编辑:
列表由CGLIB装饰。当我删除CGLIB代理时,Mockito按预期工作。任何想法在使用CGLIB代理时如何解决这样的问题?
List is decorated by CGLIB. When I remove CGLIB proxy Mockito works as expected. Any Idea how to solve such problem when using CGLIB proxies?
谢谢,
Maciej
Thanks,Maciej
推荐答案
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;
}
}
}
上面的示例产生输出:
*** 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
现在 TEST 2
和 TEST 4
应抛出 NullPointerException
on GET
通话 - 基于间谍的Mockito: doThrow(新NullPointerException异常( 我的测试空指针))时(spyMs1)获得();
Now the TEST 2
and TEST 4
should throw NullPointerException
on get
call - based on mockito spy: doThrow(new NullPointerException("my test nullpointer")).when(spyMs1).get();
TEST 4没有抛出预期的异常,因为它已经用CGLIB装饰了 - 我们也可以在控制台上看到CGLIb调用是正在执行: GLIB修饰GET调用
而不调用间谍对象。使用带有CGLIB代理的Spring AOP时,可以获得相同的效果。
The "TEST 4" does not throw expected exception because it is already decorated with CGLIB - we can also see on the console that CGLIb call is being executed: GLIB decorated GET call
and not call on spy object. The same effect can be achived when using Spring AOP with CGLIB proxies.
这篇关于Mockito - 监视真实对象调用原始方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!