Sì, Questa è la domanda un milione di dollari. Come unit test metodi privati?
Uno sviluppatore dovrebbe testare i metodi privati nella sua base di codice? o lasciarli sulla fiducia dei metodi pubblici è un modo. Ogni sviluppatore ha la sua opinione sul fatto che dovremmo effettivamente testarli o meno. Quindi, in poche parole, la domanda è stata ridotta a ” Esiste un buon approccio che possiamo provare per questo lavoro?”
Quindi, ecco tutte le possibili opzioni disponibili per uno sviluppatore per testare i metodi privati delle sue app basate su Java / kotlin nel 2019:
- Non testare metodi privati 😜(Senza radici, senza uva acerba)
- Dare ai metodi l’accesso pubblico 😒 (No, non lo farò è contro le pratiche di codifica. Sono un buon sviluppatore, seguo le migliori pratiche)
- Usa una classe di test nidificata 😒 (Questo non va bene per il codice di produzione misto con il codice di test. Devo menzionare di nuovo che sono un buon sviluppatore e seguo solo le migliori pratiche)
- Usa Java Reflection 😃(Sì, questo sembra interessante ci sto dentro)
Nonostante la credenza comune che sia effettivamente possibile accedere a campi privati e metodi di altre classi tramite Java Reflection. Non è nemmeno così difficile. Questo può essere molto utile durante il test delle unità.
Nota: funziona solo quando si esegue il codice come applicazione Java autonoma, come si fa con i test unitari e le applicazioni regolari. Se provi a farlo all’interno di un’applet Java, dovrai armeggiare con SecurityManager. Ma, dal momento che non è qualcosa che devi fare molto spesso, è rimasto fuori da questo testo finora.
Il supporto per la riflessione dei parametri del metodo è stato aggiunto in Java 8. In poche parole, fornisce supporto per ottenere i nomi dei parametri in fase di esecuzione.
Per accedere a un campo privato è necessario chiamare il metodoClass.getDeclaredField(String name)
oClass.getDeclaredFields()
. I metodi Class.getField(String name)
e Class.getFields()
restituiscono solo campi pubblici, quindi non funzioneranno. Ecco un semplice esempio di una classe con un campo privato, e di seguito il codice per accedere a tale campo di via Java Riflessione:
public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}
}PrivateObject privateObject = new PrivateObject("The Private Value");Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");privateStringField.setAccessible(true);String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
in Questo esempio di codice stamperà il testo "fieldValue = The Private Value”
quale è il valore del campo privato privateString
di PrivateObject
l’istanza creata all’inizio del codice di esempio.
Si noti l’uso del metodo PrivateObject.class.getDeclaredField("privateString")
. È questa chiamata al metodo che restituisce il campo privato. Questo metodo restituisce solo i campi dichiarati in quella particolare classe, non i campi dichiarati in qualsiasi superclasse.
Si noti la linea in grassetto troppo. Chiamando Field.setAcessible(true)
si disabilitano i controlli di accesso per questa particolare istanzaField
, solo per riflessione. Ora è possibile accedervi anche se è privato, protetto o ambito del pacchetto, anche se il chiamante non fa parte di tali ambiti. Non è ancora possibile accedere al campo utilizzando il codice normale. Il compilatore non lo permetterà.
Accesso ai metodi privati
Per accedere a un metodo privato è necessario chiamare il metodoClass.getDeclaredMethod(String name, Class parameterTypes)
oClass.getDeclaredMethods()
. I metodi Class.getMethod(String name, Class parameterTypes)
eClass.getMethods()
restituiscono solo metodi pubblici, quindi non funzioneranno.
Ecco un semplice esempio di una classe con un metodo privato, e di seguito il codice per accedere a tale metodo tramite Java Reflection:
public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}private String getPrivateString(){
return this.privateString;
}
}PrivateObject privateObject = new PrivateObject("The Private Value");Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);privateStringMethod.setAccessible(true);String returnValue = (String)
privateStringMethod.invoke(privateObject, null);System.out.println("returnValue = " + returnValue);
in Questo esempio di codice stamperà il testo "returnValue = The Private Value”
, che è il valore restituito dal metodo getPrivateString()
quando viene richiamato il PrivateObject
l’istanza creata all’inizio del codice di esempio.
Si noti l’uso del metodo PrivateObject.class.getDeclaredMethod("privateString")
. È questa chiamata al metodo che restituisce il metodo privato. Questo metodo restituisce solo i metodi dichiarati in quella particolare classe, non i metodi dichiarati in nessuna superclasse.
Si noti la linea in grassetto troppo. Chiamando Method.setAcessible(true)
si disattiva i controlli di accesso per questa particolare istanzaMethod
, solo per riflessione. Ora è possibile accedervi anche se è privato, protetto o ambito del pacchetto, anche se il chiamante non fa parte di tali ambiti. Non è ancora possibile accedere al metodo utilizzando il codice normale. Il compilatore non lo permetterà.
Proviamo questa conoscenza con un codice a livello di produzione.
Ecco la classe contenente alcuni metodi privati che vogliamo testare.