2011-11-29 11 views
16

Voglio prendere in giro un metodo protetto ereditato. Non posso chiamare questo metodo direttamente dal codice java in quanto è ereditato dalla classe che in un altro pacchetto. Non riesco a trovare un modo per specificare questo metodo per stub in a when(...)metodo protetto di simulazione

package a; 

public class A() { 
    protected int m() {} 
} 

package b; 

public class B extends a.A { 
    // this class currently does not override m method from a.A 
    public asd() {} 
} 

// test 
package b; 

class BTest { 
    @Test 
    public void testClass() { 
     B instance = PowerMockito.spy(new B()); 
     PowerMockito.when(instance, <specify a method m>).thenReturn(123); 
     //PowerMockito.when(instance.m()).thenReturn(123); -- obviously does not work 
    } 
} 

ho guardato PowerMockito.when le sostituzioni e questo sembra che sono tutti solo per i metodi privati!

Come specificare il metodo protetto?

+0

@AndroidKiller, codice aggiornato con nome classe. In realtà potrebbero essere da Mockito, ma io uso powermock e questi metodi hanno lo stesso significato lì –

+0

Questo è il motivo per cui dovremmo sempre preferire la composizione sull'ereditarietà. Se non puoi ridefinire questo metodo nel tuo codice testato, proprio come faresti con il codice legacy. – Brice

risposta

24

In poche parole: non è possibile utilizzare sempre when per stub spie; utilizzare doReturn.

Assumendo importazioni statiche di spy e doReturn (sia PowerMockito):

@RunWith(PowerMockRunner.class) 
@PrepareForTest(B.class) 
public class BTest { 
    @Test public void testClass() throws Exception { 
     B b = spy(new B()); 
     doReturn(42).when(b, "m"); 
     b.asd(); 
    } 
} 

Si potrebbe anche @PrepareForTest(A.class) e impostare il doReturn su when(a, "m"). Il che ha più senso dipende dal test effettivo.

+0

wow, grazie. È interessante notare che quando ho provato a utilizzare l'istanza di Method invece del metodo stringa, il nome stubbing non è riuscito con il messaggio di eccezione sul numero errato di argomenti. Ma con il nome della stringa tutto funziona perfettamente. –

+0

@mishanesterenko Sì, a volte può diventare un po 'complicato. Un'altra opzione è sempre la sottoclasse di 'B' ai fini del test. Non sempre un'opzione, ma meno "magica" della modifica del bytecode;) –

+0

Cosa faresti se hai impostato il metodo di restituzione di void. Diciamo che 'm' è un metodo-set come void m (parser MySpecialParser). Questo parser è usato per analizzare il mio testo. Come posso deriderlo? – Kayser