Supponiamo che io abbia una class del genere:
public class MyClass { Dao dao; public String myMethod(Dao d) { dao = d; String result = dao.query(); return result; } }
Voglio testarlo con il mockito. Così creo un object fittizio e chiamo il metodo per testarlo in questo modo:
Dao mock = Mockito.mock(Dao.class); Mockito.when(mock.myMethod()).thenReturn("ok"); new MyClass().myMethod(mock);
Ma, supponiamo che io abbia una class del genere:
public class MyClass { Dao dao = new Dao(); public String myMethod() { String result = dao.query(); return result; } }
Ora non posso passare il mio scherzo come argomento, quindi come posso testare il mio metodo? Qualcuno può mostrare un esempio?
Fondamentalmente, stai cercando di sostituire un campo privato con un’implementazione alternativa, il che significa che violerai l’incapsulamento. L’unica altra opzione è quella di ristrutturare la class o il metodo, per renderlo meglio progettato per il test.
Ci sono molte risposte brevi nei commenti, quindi li sto aggregando qui (e aggiungendo un paio di miei) come Wiki della comunità. Se hai qualche alternativa, sentiti libero di aggiungerli qui.
Creare un override per l’iniezione delle dipendenze o un metodo statico che accetta un DAO e rendere delegato il metodo di istanza pubblico. Prova invece il metodo più flessibile.
public String myMethod() { return myMethod(dao); } String myMethod(Dao dao) { /* real implementation here */ }
Si noti che alcuni di questi possono essere privati dei pacchetti per il test, se si mettono i test nello stesso pacchetto Java (possibilmente in un albero dei sorgenti separato). In tutti i casi, i buoni nomi e la documentazione sono utili per chiarire le vostre intenzioni.
Dao
con una simulazione di tua scelta. ( Dave Newton ) cosa ne pensi di questo?
public class MyClassTest { MyClass myClass = new MyClass(); Dao dao = Mockito.mock(Dao.class); public void testMyMethod() { Field field = myClass.getClass().getDeclaredField("dao"); field.setAccessible(true); field.set(myClass, dao); //Do the test... } }
EDIT: Come menzionato nei commenti, si presume che non si cambi il nome del campo dao
. Potrebbe essere una buona idea quindi ottenere tutti i campi Field[] fields = myClass.getClass().getDeclaredFields();
e scorrere su di loro, ottenendo il campo (s) di tipo Dao. Quindi procedere come sopra. In questo modo il tuo test non dipende più dal nome del tuo campo.