2013-05-06 4 views
7

Ho iniziato davvero a utilizzare TDD e ho iniziato a utilizzare mockito in jUnit per migliorare la mia capacità di testare il codice. Sto davvero amando il mockito!chiama il metodo statico sul parametro senza istanziare la classe nell'argomento

Ho notato che devo cambiare il mio modo di pensare di codifica, come passare i collaboratori, per quanto possibile in metodi e limitando il lavoro svolto nei costruttori, ove possibile.

Il seguente scenario ha giustificato alcuni consigli degli esperti qui su SO.

Supponiamo che abbia un metodo, che chiamerà alcuni metodi statici su una determinata classe. PER ESEMPIO.

public void method(){ 
    OtherClass.staticMethod(); 
} 

Questo è generalmente cattivo, ma è necessario nel mio scenario. Per rendere il codice più testabile nei miei test di unità vorrei evitare la dipendenza da OtherClass e passarlo come argomento.

Questo non funziona in quanto genera un errore in fase di compilazione.

public void method(Class<? extends OtherClass> util){ 
    util.staticMethod(); 
} 
... 
method(OtherClass.class); 

Questo potrebbe funzionare, ma non mi piace l'OtherClass un'istanza se non devo, in quanto è solo una classe di utilità statico come metodi:

public void method(OtherClass util){ 
    util.staticMethod(); 
} 
... 
method(new OtherClass()); 

La mia domanda a voi : Esiste un modo migliore, più preferibile, per eseguire ciò senza utilizzare la nuova parola chiave?

+2

Domanda molto ben formattata per un nuovo utente, congratulazioni :) – MarioDS

+0

Non sono sicuro se il tuo ultimo codice verrà comunicato se passi un'istanza di una sottoclasse di 'OtherClass'. L'accesso ai metodi statici tramite un'istanza mi sembra fonte di confusione in quanto ** non è correlato a quell'istanza **, e potrebbe non funzionare nel modo in cui si pensa che sarebbe. –

+0

BTW, utilizzare ** Pattern Singleton ** invece di metodi statici nel tuo caso? –

risposta

0

Nel codice di esempio:

public void method(){ 
    OtherClass.staticMethod(); 
} 

mia comprensione è, ci dovrebbe essere una certa logica nel metodo di cui sopra a parte chiamata di metodo statico, ed è quello che si desidera verificare e non metodo statico.

In tal caso è possibile scrivere un'implementazione fittizia di OtherClass.staticMethod che ignorerà tutta la logica o restituirà il valore desiderato o implementerà una logica specifica. Ciò eviterà la dipendenza da OtherClass e fornirà controlli espliciti su di esso.

0

È possibile utilizzare il primo approccio per cambiare il vostro metodo come questo

public void method(Class<? extends OtherClass> clazz) throws Exception { 
    Method[] mArray = clazz.getMethods(); 
    for(Method m :mArray) { 
     if(!m.isAccessible()) m.setAccessible(true); 
     if((m.getModifiers() & Modifier.STATIC) != 0) { // Here a method which is static is executed. You can change this condition, to suit your needs 
      m.invoke(null); 
     } 
    } 
} 

E si può invocarlo chiamando

method(OtherClass.class); 

senza passare un nuovo oggetto di quella classe

0

È possibile utilizzare la riflessione:

// exceptions management omitted 
public void method(Class<? extends OtherClass> clazz, String methodName) { 
    // methodName could also be a constant if it won't change 
    clazz.getMethod(methodName).invoke(null); 
} 

Poi,

method(OtherClass.class, "staticMethod"); 
0

Ecco quello che ho appena provato:

public void testMethod(Class<T> clazz) throws Exception{   
     Method m = clazz.getMethod("staticMethod",null); 
     m.invoke(null,null); 
    } 

ho pensato (come indicato nel tuo esempio) che il metodo statico non prende alcun argomento.

Consultare i documenti dei metodi getMethod() e inovke().

0

Niente di male in un po 'di codice statico qua e là - se non accede uno stato globale:

Se il codice statico è puramente procedurale

public void method(){ 
    OtherClass.staticMethod(); 
} 

Puoi prendi in giro il metodo(), purché tu mantenga la chiamata statica come unica operazione nel tuo metodo

Altrimenti se il tuo metodo statico protegge qualche stato globale, saresti meglio con un Singleton + Locator

public class Registry { 
    DoSomethingInterface getOtherClass() { 
     return OtherClass.getSingleton(); 
    } 
} 


public void method(Registry reg){ 
    reg.getOtherClass().doSomething(); 
} 

è quindi possibile creare una sottoclasse del Registro di sistema per fornire ogni tipo di variante al localizzatore getOtherClass(), in modo da poter avere un TestRegistry istanziato in tempi di test prendersi cura di fornendo uno stato globale pulito e altre cose

Se hai ancora bisogno l'altra classe ad essere statico, perché non è possibile modificare in alcun modo (vale a dire Class Library), è possibile avvolgere nella vostra interfaccia:

public class Registry { 
    DoSomethingInterface getOtherClass() { 
     return new DoSomethingInterface(){ 
      public void doSomething() { 
       OtherClass.staticMethod(); 
      } 
     }; 
    } 
} 
1

Questo avrebbe funzionato, ma non mi piace l'OtherClass un'istanza se non devo, come è solo un classe di utilità statico come metodi:

public void method(OtherClass util){ 
    util.staticMethod(); 
} 
... 
method(new OtherClass()); 

realtà, questo non funziona, come sarà sempre richiamare l'implementazione del metodo da OtherClass, indipendentemente l'oggetto si passa (anche se si passa 0.123.).

Si consiglia vivamente di non utilizzare la riflessione solo per semplificare il test, in quanto ciò ignora il controllo del tempo di compilazione (un nome di metodo errato non verrà rilevato dal compilatore) e impedisce l'utilizzo di molte funzionalità dell'IDE (completamento del codice , javadoc si libra, supporta il refactoring, visualizza la gerarchia delle chiamate, passa alla definizione, ...)

L'approccio comune è quello di utilizzare la spedizione polimorfica. In Java, questo richiede che il metodo non sia statico e non privato. La regola generale è quindi: se ha bisogno di deridere, non dovrebbe essere statico.

Come ottenere meglio l'istanza dell'oggetto dipende dalle circostanze; l'iniezione di dipendenza (il tuo approccio), il modello di individuazione delle risorse e il modello singleton hanno ciascuno i loro vantaggi e svantaggi.

Problemi correlati