2012-05-26 17 views
5

Sto scrivendo un test delle unità usando JUnit + Mockito per testare un metodo come:derisione una chiamata su un metodo pubblico di una classe astratta, senza sottoclasse della classe astratta, utilizzando Mockito prefererably

public someObject methodUnderTest(){ 
    SomeObject obj = SomeAbstractClass.someMethod(); 

    if(obj!=null){ 
    obj.someOtherMethod(); 
    } 

    return someThing; 
} 

e vorrei deridere la chiamata abstract Class "SomeAbstractClass" menzionato nel frammento di codice di cui sopra in modo che possa verificare chiamata "obj" come:

verify(SomeAbstractClass).someMethod(); 
verify(obj).someOtherMethod(); 

ho provato con caratteristiche Mockito come: Mockito.CALLS_REAL_METHODS Mockito. RETURNS_MOCKS

ma non funzionano a causa di dipendenze non disponibili per SomeAbstractClass.

Nota:

1) SomeObject è un'interfaccia.

2) Ho bisogno di una tecnica per testare il frammento di codice sopra. Sono costretto a utilizzare il frammento di codice precedente e non posso modificare il frammento di codice.

risposta

1

Presupposto: se si scrive test di unità, credo che sia ancora possibile modificare un po 'il metodo testato.

Soluzione:

  1. estratto metodo statico chiamata al metodo override:
public someObject methodUnderTest() { 
    SomeObject obj = getSomeObject(); 

    if(obj!=null){ 
     obj.someOtherMethod(); 
    } 

    return someThing; 
} 

protected SomeObject getSomeObject() { 
    return SomeAbstractClass.someMethod(); 
} 
  1. quindi è possibile utilizzare Mockito Spy per deridere parzialmente l'oggetto in realtà di prova:
private ClassUnderTest classUnderTest; 

@Before 
public void setUp() { 
    classUnderTest= new ClassUnderTest(); 
    classUnderTest = Mockito.spy(classUnderTest); 
} 

@Test 
public void test() { 
    SomeObject someObject = Mockito.mock(SomeObject.class); 
    when(classUnderTest.getSomeObject()).thenReturn(someObject); 
    classUnderTest.methodUnderTest(); 
    verify(someObject).someOtherMethod(); 
} 

@Test 
public void testNull() { 
    when(classUnderTest.getSomeObject()).thenReturn(null); 
    classUnderTest.methodUnderTest(); 
    verify(something); 
} 
+0

Grazie miheys per il tuo aiuto. Ho fatto esattamente la stessa cosa. –

1

Utilizzare le classi anonime:

public interface SomeObject { 
    public Object someOtherMethod(); 
} 

public abstract class SomeAbstractClass { 
    abstract SomeObject someMethod(); 
} 

@Test 
public void test() { 
    SomeAbstractClass target = new SomeAbstractClass() { 
     SomeObject someMethod() { 
      // some impl 
      SomeObject someObject = new SomeObject() { 
       public Object someOtherMethod() { 
        // some other impl 
       } 
      }; 
      return someObject; 
     } 
    }; 

    // now test target 
} 
+0

Grazie Bohemian, ma ho dimenticato di menzionare che SomeObject restituito è un'interfaccia così come "SomeAbstractClass.someMethod()" è un metodo pubblico e statico. Quindi sono costretto ad implementare l'interfaccia "SomeObject" che non voglio fare, sia "SomeAbstractClass" che "SomeObject" fanno parte di una libreria di terze parti che sto usando nella mia applicazione web. –

+0

Puoi anche usare una classe anonima per un'interfaccia (come SomeObject) - vedi la risposta modificata – Bohemian

2

È possibile utilizzare PowerMock per deridere i metodi statici e finali.

2

Sembra che il problema è che l'utilizzo del CALLS_REAL_METHODS sta applicando a tutta la classe, dove si vuole veramente prendere in giro i metodi specifici (vale a dire fare una "simulazione parziale"). Hai due opzioni qui, uno che utilizza thenCallRealMethod, e una con CALLS_REAL_METHODS e poi specificamente beffardo le chiamate è necessario:

public void testMethodUnderTest_mockSpecificThings() { 
    SomeAbstractClass myAbstractClass = Mockito.mock(SomeAbstractClass.class); 
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class); 
    when(myAbstractClass.someMethod()).thenReturn(foo); 
    when(myAbstractClass.methodUnderTest()).thenCallRealMethod(); 

    myAbstractClass.methodUnderTest(); 

    verify(myAbstractClass).someMethod(); 
    verify(myObject).someOtherMethod(); 
} 

public void testMethodUnderTest_makeSpecificRealCalls() { 
    SomeAbstractClass myAbstractClass = 
     Mockito.mock(SomeAbstractClass.class, CALLS_REAL_METHODS); 
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class); 
    // overrides the default answer 
    when(myAbstractClass.someMethod()).thenReturn(myObject); 

    myAbstractClass.methodUnderTest(); 

    verify(myAbstractClass).someMethod(); 
    verify(myObject).someOtherMethod(); 
} 

sappiate che SomeAbstractClass non è mai in realtà un'istanza, quindi se ci si basa su alcun comportamento in classe astratta costruttore, come l'inizializzazione delle variabili - inclusa l'inizializzazione inline in cui sono dichiarati i campi - sarà necessario effettuare tali chiamate in modo esplicito.

Problemi correlati