2013-07-30 6 views
9

Sto provando a testare una classe astratta e Mockito non inizializza le mie variabili membro. Ecco un semplice esempio per mostrarti il ​​mio problema.Perché Mockito salta l'inizializzazione della variabile membro della mia classe astratta

Questa è una classe astratta che inizializza il proprio 'campo' membro:

import java.util.ArrayList; 
import java.util.Collection; 

public abstract class Foo { 
    private final Collection field = new ArrayList(); 

    protected Foo() { 
     System.out.println("In constructor"); 
    } 

    public boolean isNull(Object o) { 
     field.add(o); 

     return o == null; 
    } 

    abstract void someAbstractMethod(); 
} 

Qui la classe di test:

import org.junit.Assert; 
import org.junit.Test; 
import org.mockito.Mockito; 

public class FooTest { 
    @Test 
    public void testSomething() { 
     final Foo foo = Mockito.mock(Foo.class); 

     Mockito.when(foo.isNull(Mockito.anyObject())).thenCallRealMethod(); 

     Assert.assertFalse(foo.isNull("baaba")); 
    } 
} 

Quando il test viene eseguito getta un NPE perché il campo variabile' 'non è inizializzato!

Cosa sto sbagliando?

+0

L'utilizzo di http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html#thenCallRealMethod%28%29 non è consigliato. Cosa vuoi testare? Se è l'implementazione di alcuni metodi di Foo, quindi crea semplicemente una sottoclasse. Utilizzare Mockito, quando si desidera verificare il comportamento o le chiamate al metodo di stub. –

+0

Come ho detto a [@ david-wallace] (http://stackoverflow.com/users/1081110/david-wallace), voglio testare la classe astratta. La mia intenzione di usare una simulazione era di prevenire errori di compilazione in caso di cambiamento della classe astratta o di una delle sue interfacce. – Pigelvy

risposta

4

Questo è il comportamento previsto, quando si prende in giro qualcosa l'istanza creata è una simulazione completa, quindi non ha senso inizializzare i campi poiché il comportamento è predefinito.

A parte ciò, i campi possono essere inizializzati da un costruttore in classi concrete o astratte, poiché l'istanziazione dei mock bypassa il costruttore semplicemente perché è una simulazione, è ancora più irrazionale inizializzarli.

Cercare di chiamare il metodo reale di solito è sbagliato quando si usano i mock. Invece si dovrebbe bloccare il comportamento della simulazione.

Mockito.when(foo.isNull(Mockito.anyObject())).thenReturn(false); 
Assert.assertFalse(foo.isNull("baaba")); // assertion always passing 

io non conosco il tuo caso d'uso effettivo, ma forse si vuole un mock parziali, con un spy. Anche se questo è ancora considerato una cattiva pratica in quanto di solito significa che è necessario rifattorizzare il codice per utilizzare la composizione.

+0

Mi aspettavo che Mockito facesse qualcosa che non era stato progettato per fare. Come discusso con [@ David-Wallace] (http://stackoverflow.com/users/1081110/david-wallace), creerò un'implementazione fittizia nei miei test che dovrò mantenere se i metodi verranno aggiunti/rimossi. Thx – Pigelvy

+0

È questo il comportamento previsto anche per i membri statici? Ho provato e Mockito ha richiesto l'inizializzazione dei membri statici, dovrebbe saltare anche questa inizializzazione? – dushyantashu

+0

I membri statici @dushyantashu vengono inizializzati dal classloader quando viene caricata la classe. Mockito non lo cambia. – Brice

3

Sembra che tu stia prendendo in giro la classe che stai effettivamente cercando di testare. Non è proprio l'idea di prendere in giro. Ti prendi in giro le classi che non rientrano nell'ambito del test e lasci che la cosa che stai testando non sia bloccata.

In questo caso, dovresti probabilmente creare un Foo, con un'implementazione fittizia di someAbstractMethod e testarlo direttamente. Non c'è bisogno di deriderlo, per quanto posso vedere.

+0

In effetti, voglio prendere in giro la classe astratta che sto testando in modo che i test non falliscano ogni volta che un nuovo metodo astratto viene aggiunto a quella classe (o una delle sue interfacce). E 'davvero una cattiva pratica? – Pigelvy

+0

Non ho esperienza sufficiente per deporre la legge su cosa sia una "cattiva pratica" e cosa no. Ma sembra piuttosto come usare uno scalpello come un cacciavite. Non è per cosa sono stati progettati i mock.Il mio istinto sarebbe solo quello di continuare a testare la tua implementazione fittizia e aggiungere i nuovi metodi ovunque siano necessari. Immagino che dipenda dalla frequenza con cui si desidera aggiungere un nuovo metodo astratto alla classe - se si tratta di un evento frequente, probabilmente si applica il punto di Brice sul refactoring dell'uso della composizione. La risposta alla tua domanda è che Mockito non è mai stato concepito per ... –

+0

... inizializza i campi nei suoi banchi; ora armato di quella conoscenza, vai avanti e fai i tuoi test in qualsiasi modo ti si addica meglio. –

Problemi correlati