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;
}
}
}
esempio precedente produce un output:
*** 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
Ora il TEST 2
e TEST 4
dovrebbe gettare NullPointerException
su get
chiamata - sulla base di spionaggio Mockito: doThrow(new NullPointerException("my test nullpointer")).when(spyMs1).get();
la "prova 4" non si butta previsto eccezione perché è già decorata con CGLIB - possiamo anche vedere sulla console che la chiamata CGLIb è in esecuzione: GLIB decorated GET call
e non chiamare su oggetto spia. Lo stesso effetto può essere ottenuto quando si utilizza Spring AOP con i proxy CGLIB.
fonte
2012-02-08 16:28:13
Sembra che questa sia solo la sintassi di mockito, che utilizza il modello di builder. (come molti altri modelli di derisione) –
Per quanto ne sappia Mockito, il tuo codice è corretto. La documentazione dice che 'doThrow' è solo per i metodi void, quindi puoi provare di nuovo ad es. 'clear()' per vedere se questo è il problema. Ma non riesco davvero a immaginare perché 'doThrow' non dovrebbe funzionare su metodi non void come' doReturn' fa. – flyx
Non sei sicuro di cosa stai chiedendo qui. Sì, puoi usare doThrow(), anche per i metodi non void. Il motivo per cui i documenti menzionano i metodi void è perché esiste una seconda sintassi per i lanci di stub, che non funziona per i metodi void, e che viene presentata prima di quella successiva nei documenti. Il get (0) nel tuo esempio viene chiamato solo sulla spia, non sulla lista reale. La spia sa che è nel contesto di un doThrow, quindi invece di chiamare il valore REAL get (0), lo stub invece. È questo che stai chiedendo? Se è così, trasformerò questo commento in una risposta. –