2015-12-29 10 views
6

Il mio scenario è piuttosto semplice. Cercando di usare le derisioni parziali, secondo l'ultima risposta su e the documentation of Mockito stesso. La mia prova è:Mockito Spy - parziale beffardo non funziona?

@Test 
public void test() { 
    ClassUnderTest realObject = new ClassUnderTest(); 
    ClassUnderTest spy = spy(realObject); 
    when(spy.methodB()).thenThrow(new Exception("Testing")); 

    spy.methodA(); 
} 

e la classe in prova è:

import org.apache.commons.lang3.NotImplementedException; 

public class ClassUnderTest { 

    int methodB(){ 
     throw new NotImplementedException("Not implemented"); 
    } 

    public int methodA(){ 
     methodB(); 
     return 0; 
    } 

} 

Mi aspetterei che il mio oggetto di spionaggio avrebbe chiamato il metodo B sollevando l'eccezione "Testing", mentre in realtà il vero e proprio metodo viene chiamato lancio dell'eccezione "Non implementata". Si comporta come se non avessi un comportamento simulato parziale sul posto

Perché è così? Cosa mi manca?

EDIT: Come suggerito RPresle, ho provato ad utilizzare la sintassi

doThrow(new Exception("Testing")).when(spy.methodB()); 

Tuttavia, ottengo un UnfinishedStubbingException:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at SimpleTest.test(SimpleTest.java:15) 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
when(mock.isOk()).thenReturn(true); 
when(mock.isOk()).thenThrow(exception); 
doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed 

at SimpleTest.test(SimpleTest.java:15) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

Qualcuno potrebbe fornire maggiori indicazioni?

+2

Hai fatto '.Quando (spy.methodB());' mentre RPresle scritto '.Quando (spia) .methodB();' – QBrute

+0

Hai ragione. Grazie mille. Pensi che dovrei rimuovere la mia modifica o il mio "errore" potrebbe essere utile per i futuri lettori? –

risposta

9

Facendo riferimento a this tutorial su Mockito, è possibile vedere che Mockito chiama il metodo originale.

C'è solo un avvertimento su questa sintassi. Il vero metodo rule.createFileTemplate() verrà chiamato una volta. Questo può avere un sacco di effetti collaterali e potrebbe anche fallire nel lanciare un'eccezione (molto spesso un NPE). Per risolvere questo problema, è possibile (? Dovrebbe) utilizzare questa sintassi Mockito alternativa:

doReturn(mockFileTemplate).when(rule).createFileTemplate(); 

Per evitare questo si dovrebbe usare l'altra sintassi Mockito doReturn().when()

doThrow(new Exception("Testing")).when(spy).methodB(); 

Spero che questo aiuto.

EDIT:

Si prega di notare che la struttura è un po 'diverso rispetto al when().thenReturn().

doThrow(new Exception("Testing")) 
    .when(spy) 
    .methodB(); 
+0

Grazie mille per la risposta. Per favore controlla la mia domanda modificata ... –

Problemi correlati