2015-08-18 13 views
5

Come utilizzare Mockito o PowerMock per simulare un metodo protetto realizzato da una sottoclasse, ma ereditato da una super classe astratta?Come simulare il metodo protetto di sottoclasse ereditato dalla classe astratta?

In altre parole, voglio testare il metodo "doSomething" mentre sto prendendo in giro "doSomethingElse".

astratta super-classe

public abstract class TypeA { 

    public void doSomething() {  

     // Calls for subclass behavior 
     doSomethingElse();  
    } 

    protected abstract String doSomethingElse(); 

} 

implementazione di sottoclasse

public class TypeB extends TypeA { 

    @Override 
    protected String doSomethingElse() { 
     return "this method needs to be mocked"; 
    } 

} 

Solution

risposte qui riportati sono corretti un d funzionerà se le classi coinvolte sono nello stesso pacchetto.

Ma se pacchetti diversi sono coinvolti, un'opzione è per l'utente PowerMock. Il seguente esempio ha funzionato per me. Naturalmente ci potrebbero essere altri modi per farlo, questo è quello che funziona.

import static org.junit.Assert.assertEquals; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ TypeB.class }) 
public class TestAbstract { 

    @Test 
    public void test_UsingPowerMock() throws Exception { 
     // Spy a subclass using PowerMock 
     TypeB b = PowerMockito.spy(new TypeB()); 
     String expected = "some value for mock"; 

     // Mock a method by its name using PowerMock again 
     PowerMockito.doReturn(expected).when(b, "doSomethingElse"); 

     // Calls the 
     String actual = b.doSomething(); 
     assertEquals(expected, actual);  

    } 
} 

Nota: Prove eseguite usando Java 5, JUnit 4.11, Mockito 1.9.0 e 1.4.12 PowerMock.

+1

Questo approccio mi dà un 'NullPointerException' con Java 8, JUnit 4.12 e PowerMock 1.6.4. – Mack

risposta

5

È possibile utilizzare Mockito.CALLS_REAL_METHODS quando beffardo il metodo astratto. Questo chiamerà i metodi originali della classe e potrai prendere in giro tutti i metodi astratti da solo.

TypeA typeA = mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 
when(typeA.doSomethingElse()).thenReturn("Hello"); 
typeA.doSomething(); 

Oppure si prova direttamente sul TypeB con una spia:

TypeB typeB = spy(new TypeB()); 
when(typeB.doSomethingElse()).thenReturn("Hello"); 
typeB.doSomething(); 
+1

La prima opzione fallisce perché TypeA è astratto. L'opzione 2 funziona con 'spy()' ma quando provo ad applicarlo nel mio codice di produzione mi dà 'Il metodo dal tipo non è visibile'. Cercando di capire perché. – BonanzaOne

+0

In realtà il test è corretto, ma ho classi che sono in pacchetti diversi, ecco perché non ero in grado di farlo prima. I metodi non sono visibili da altri pacchetti quando sono protetti. – BonanzaOne

+0

Anche la prima opzione funziona?Ho testato entrambi con Mockito 1.10.19 e l'ultima versione beta e funzionano entrambi come previsto. – mszalbach

3

È possibile verificare la classe abtract utilizzando Mockito nel seguente modo

TypeA typA = Mockito.mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 
when(typA.doSomethingElse()).thenReturn("doSomethingElse"); 
Assert.assertSomething(typeA.doSomething()); 
4

Io suggerisco di usare Mockito per questo:

// Create a new Mock 
final TypeA a = Mockito.mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 

// Call the method 
a.doSomething(); 

// Now verify that our mocked class' method was called 
Mockito.verify(a, Mockito.times(1)).doSomethingElse(); 
+0

Funziona, ma ho appena realizzato che ho classi in pacchetti diversi nel mio codice di produzione. I metodi protetti non sono quindi visibili. – BonanzaOne

+0

Questo lo rende un problema. Una possibile soluzione sarebbe quella di utilizzare PowerMock, che dovrebbe essere in grado di verificare i metodi privati, afaik. Mai usato, però. –

2

a metodi finta che restituisce vuoto in classi astratte abbiamo potuto usare:

MyAbstractClass abs = Mockito.mock(MyAbstractClass.class); 
Mockito.doNothing().when(abs).myMethod(arg1,arg2....)); 

possiamo sostituire gli argomenti con Mockito.anyString() ecc secondo i requisiti.

Problemi correlati