JUNIT testare metodi void

Ho una class java piena di metodi void, e voglio fare qualche test unitario per ottenere la massima copertura del codice.

Ad esempio, ho questo metodo:

protected static void checkifValidElements(int arg1, int arg2) { method1(arg1); method2(arg1); method3(arg1, arg2); method4(arg1, arg2); method5(arg1); method6(arg2); method7(); } 

È mal chiamato perché ha tradotto il codice per una migliore comprensione. Ogni metodo verifica se gli argomenti sono validi in qualche modo e sono ben scritti.

Esempio :

 private static void method1(arg1) { if (arg1.indexOf("$") == -1) { //Add an error message ErrorFile.errorMessages.add("There is a dollar sign in the specified parameter"); } } 

Il mio test unitario copre bene i piccoli metodi perché chiedo loro di controllare se ErrorFile contiene il messaggio di errore, ma non vedo come posso testare il mio metodo checkIfValidElements, non restituisce nulla o non modifica nulla. Quando eseguo la copertura del codice con Maven, mi dice che il test unitario riguarda questa parte della mia class.

L’unico modo che vedo è di cambiare questo metodo per restituire un valore int o bollean, come questo:

 protected static int checkifValidElements(int arg1, int arg2) { method1(arg1); method2(arg1); method3(arg1, arg2); method4(arg1, arg2); method5(arg1); method6(arg2); method7(); return 0; } 

Con questo metodo sono in grado di fare un’asserzione uguale, ma mi sembra che sia inutile farlo. Il problema è che ho un paio di classi progettate in questo modo e che riducono la mia percentuale di copertura del test unitario.

Voglio fare qualche test unitario per ottenere la massima copertura del codice

La copertura del codice non dovrebbe mai essere l’ objective della scrittura dei test unitari. Dovresti scrivere dei test unitari per dimostrare che il tuo codice è corretto, o aiutarti a progettarlo meglio, o aiutare qualcun altro a capire che cosa il codice è destinato a fare.

ma non vedo come posso testare il mio metodo checkIfValidElements, non restituisce nulla o non cambia nulla.

Beh, probabilmente dovresti dare qualche test, che tra loro controlla che tutti i 7 metodi siano chiamati appropriatamente – entrambi con un argomento non valido e con un argomento valido, controllando i risultati di ErrorFile ogni volta.

Ad esempio, supponiamo che qualcuno abbia rimosso la chiamata a:

 method4(arg1, arg2); 

… o accidentalmente cambiato l’ordine degli argomenti:

 method4(arg2, arg1); 

Come noteresti questi problemi? Passa da questo e progetta test per provarlo.

Se il tuo metodo non ha effetti collaterali e non restituisce nulla, allora non sta facendo nulla.

Se il tuo metodo esegue alcuni calcoli e restituisce il risultato di quel calcolo, puoi chiaramente affermare che il risultato restituito è corretto.

Se il tuo codice non restituisce nulla, ma ha effetti collaterali, puoi chiamare il codice e quindi affermare che sono stati eseguiti gli effetti collaterali corretti. Quali sono gli effetti collaterali determinerà come eseguire i controlli.

Nel tuo esempio, stai chiamando metodi statici dalle tue funzioni di non ritorno, il che lo rende difficile a meno che tu non possa controllare che il risultato di tutti quei metodi statici siano corretti. Un modo migliore – da un punto di vista del test – è quello di iniettare oggetti reali in cui si chiamano i metodi. È quindi ansible utilizzare qualcosa come EasyMock o Mockito per creare un object Mock nel test dell’unità e iniettare l’object mock nella class. L’Oggetto Mock ti consente quindi di affermare che sono state chiamate le funzioni corrette, con i valori corretti e nell’ordine corretto.

Per esempio:

 private ErrorFile errorFile; public void setErrorFile(ErrorFile errorFile) { this.errorFile = errorFile; } private void method1(arg1) { if (arg1.indexOf("$") == -1) { //Add an error message errorFile.addErrorMessage("There is a dollar sign in the specified parameter"); } } 

Quindi nel tuo test puoi scrivere:

 public void testMethod1() { ErrorFile errorFile = EasyMock.createMock(ErrorFile.class); errorFile.addErrorMessage("There is a dollar sign in the specified parameter"); EasyMock.expectLastCall(errorFile); EasyMock.replay(errorFile); ClassToTest classToTest = new ClassToTest(); classToTest.setErrorFile(errorFile); classToTest.method1("a$b"); EasyMock.verify(errorFile); // This will fail the test if the required addErrorMessage call didn't happen } 

Puoi ancora testare un metodo di annullamento affermando che ha avuto l’effetto collaterale appropriato. Nell’esempio method1 , il tuo test unitario potrebbe essere simile a:

 public void checkIfValidElementsWithDollarSign() { checkIfValidElement("$",19); assert ErrorFile.errorMessages.contains("There is a dollar sign in the specified parameter"); } 

Puoi imparare qualcosa chiamato “beffardo”. È ansible utilizzare questo, ad esempio, per verificare se: – una funzione è stata chiamata – una funzione è stata chiamata x volte – una funzione è stata chiamata almeno x volte – è stata richiamata una funzione con un set specifico di parametri. Nel tuo caso, ad esempio, puoi usare il mocking per verificare che il metodo3 sia stato chiamato una volta con qualsiasi cosa tu passi come arg1 e arg2.

Dai uno sguardo a questi: https://code.google.com/p/mockito/ https://code.google.com/p/powermock/

Penso che dovresti evitare di scrivere un metodo di effetto collaterale. Restituisci vero o falso dal tuo metodo e puoi verificare questi metodi nei test unitari.

Se il metodo è nullo e si desidera verificare un’eccezione, è ansible utilizzare le expected : https://weblogs.java.net/blog/johnsmart/archive/2009/09/27/testing-exceptions-junit-47

Se è ansible nel tuo caso, puoi rendere i metodi method1(arg1)method7() protetti anziché privati ​​in modo che possano essere accessibili dalla class di test all’interno dello stesso pacchetto. Quindi puoi semplicemente testare tutti questi metodi separatamente.