java unit testing - in container and database testing
DESCRIPTION
Java Unit Testing - part 4TRANSCRIPT
![Page 1: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/1.jpg)
In-container and database Testing
Ing. Fabrizio GianneschiJava User Group Sardegna Onlus
http://www.jugsardegna.org
Java Unit Testing
![Page 2: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/2.jpg)
Test in-container
![Page 3: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/3.jpg)
Quando usare i mock object?
● I mock sono consigliati quando l'oggetto reale da rimpiazzare:– ha un comportamento non deterministico– è difficile da inizializzare– ha un comportamento difficile da riprodurre– è lento– ha un'interfaccia grafica– non esiste
● Oppure, quando il test necessita di invocare dei metodi che nell'oggetto reale non esistono
![Page 4: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/4.jpg)
Usare oggetti mock
● Abbiamo già visto come usare semplici oggetti mock
● Crearne di numerosi è però complicato
● Per fortuna, esistono numerosi framework già pronti all'uso:– JMock– EasyMock– rMock
● In generale, i mock sono utili per effettuare test out-container... ma possono essere usati anche per i test in-container
● Il problema è sempre il solito: controllare le dipendenze
![Page 5: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/5.jpg)
In-Container testing
● È il testing “a motore acceso”
● Si testano componenti il cui ciclo di vita è gestito da un soggetto terzo (il container)
● Ci sono casi, infatti, in cui non è possibile fare a meno del container (es: HttpSession...)
● Oppure, quando non abbiamo stub abbastanza buoni o
● Tool: Cactus
![Page 6: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/6.jpg)
Cactus
● Cactus è un framework per il testing di componenti J2EE
● Tipicamente, test unitari
● Spesso usato con Jetty, servlet container leggero e veloce– parte in circa 1s (Tomcat e altri impiegano di più)
● Poggia su JUnit ed estende alcuni suoi metodi
● La filosofia è simile a JUnit (setup, esecuzione, teardown...) ma distribuita tra client e server
![Page 7: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/7.jpg)
Nota
● Cactus è disponibile nella versione 1.7.2– per container J2EE 1.2– per container J2EE 1.3
● Non è disponibile espressamente per J2EE 1.4, anche se si può usare quello per la versione per la 1.3
● Testato con Tomcat 5.x
● NO JavaEE 5 --e non ci sono date, al riguardo :-(
● Alternative: JUnitEE, HttpUnit (incluso in Cactus), EJB3Unit...
![Page 8: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/8.jpg)
Purtroppo...
● Non è ancora compatibile con JUnit 4.x, anche se c'è un piccolo workaround...
“I found out that it's possible to run the JUnit 4.x (annotated) tests with
Cactus 1.7.2 minimaly with functionality of JUnit 3.8 tests.
It's need to use: JUnit4TestAdapter that automatically makes JUnit 3.8
compatible test from JUnit 4.x test.
There is only problem with displaying names of the tests but it's easy to
repair it in source class (JUnitVersionHelper) of Cactus.”
![Page 9: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/9.jpg)
Workaround
import junit.framework.JUnit4TestAdapter;...public static junit.framework.Test suite() { return new Junit4TestAdapter(<classname>.class);}...
![Page 10: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/10.jpg)
Sul client
● C'è la console
● Vengono eseguiti i metodi di inizializzazione– beginXXX e endXXX
● Sono esposte interfacce che ricalcano request, response, sessione...
● Serializza la chiamata e la spedisce ad un ProxyRedirector sul server
● In risposta, vengono raccolti gli output
![Page 11: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/11.jpg)
Classi del container
Classi del container
TestCase sul server Classi del container
Server JVM
Client JVM
TestCase sul client
Proxy redirector
●beginXxx()●endXxx()
●setUp()●testXxx()●tearDown()
cfg(es: web.xml)
HttpRequest
![Page 12: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/12.jpg)
Sul server
● Vive il Proxy redirector – ServletTestRedirector– JSPTestRedirector– FilterTestRedirector
● “Sente” la chiamata, deserializza le informazioni e le interpreta– capisce che TestCase invocare (testXxx() )
● Lo inizializza con setUp()
● Lo finalizza con tearDown()
● Vivono gli oggetti del container
![Page 13: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/13.jpg)
Sul client (configurazione)
● Deve essere resa disponibile una proprietà di sistema cactus.contextURL per consentire a Cactus di chiamare il container
● Tre modi:– via command line
( java ... -Dcactus.contextURL=http://myhost/mypath )– via System.setProperty() nel codice di inizializzazione
dei test– via file di configurazione (cactus.properties) messo nel
classpath (equivale alle properties)
● Allo stesso modo, va specificato il nome della classe da usare come Proxy– cactus.servletRedirectorName = ServletTestRedirector
![Page 14: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/14.jpg)
Sul server (configurazione)
● Va modificato il web.xml con opportune entry per i proxy utilizzati:
<servlet> <servlet-name>ServletTestRedirector</servlet-name> <servlet-class> org.apache.cactus.server.ServletTestRedirector </servlet-class></servlet>...<servlet-mapping> <servlet-name>ServletTestRedirector</servlet-name> <url-pattern>/ServletTestRedirector</url-pattern></servlet-mapping>
![Page 15: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/15.jpg)
Sul server (attenzione)
● I componenti di Cactus non andrebbero inclusi nella distribuzione in produzione– rimarrebbero disponibili dall'esterno, con gravi problemi di
sicurezza
● Ricordarsi di modificare il web.xml al momento del deploy!– Sugg.: Usare un web.xml parametrico, modificato da Ant
quando serve– Nota: usare due web.xml differenti prima o poi porta al
disallineamento
● http://jakarta.apache.org/cactus/faq.html#faq_webxml_test_prod
![Page 16: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/16.jpg)
![Page 17: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/17.jpg)
Test di Servlet e JSP
![Page 18: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/18.jpg)
Testare le servlet
● Cactus mette a disposizione una serie di oggetti impliciti
● Tali oggetti hanno interfacce conformi alla Servlet API ma l'implementazione è wrappata da Cactus– request
● request.setURL(host, ctx, path)● request.addCookie(name, value)● request.setRemoteUser(...) / .setHost(...)● request.setRemoteIPAddres(...)
– config● config.setInitParameter / .setServletName
– config.getServletWrapper()● Non wrappati, ma a disposizione
– response– session
![Page 19: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/19.jpg)
Esercizio
● Creare una servlet di controllo del flusso● La servlet controlla la presenza di un parametro page
nella request● page rappresenta il nome di una pagina da caricare
● inserisce un attributo nella request– Se page inizia per “/private/”, il valore dell'attributo è il
nome della JSP di autenticazione– Altrimenti, mette page
● Verificare il funzionamento con Cactus
![Page 20: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/20.jpg)
Esercizio
● Modificare la servlet precedente in modo tale che effettui direttamente la redirezione– non solo controllo, ma anche dispatching...
● Testare con Cactus... si può?
● Sì, ma non direttamente:● Posso testare l'output della servlet● Posso verificare che il target della redirezione esista
![Page 21: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/21.jpg)
Esercizio
● Testare che una servlet riceva correttamente i dati di un form multipart/data
● Per la spedizione dei dati dal TestCase:
● http://jakarta.apache.org/cactus/faq.html#faq_send_multipart● Per la ricezione dei dati dalla servlet:– Si può utilizzare la libreria Commons FileUpload– http://www.javastaff.com/article.php?
story=20060628011504263
![Page 22: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/22.jpg)
Testare le JSP
● A differenza delle Servlet, che dovrebbero contenere solamente logica, le JSP possono presentare anche grafica
● Pertanto, si distinguono 3 casi:– test dell'HTML / XHTML generato a seguito della logica– test delle TagLib JSP– test della logica, ma in isolamento
![Page 23: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/23.jpg)
Caso 1: test dell'HTML
● Banale, estende ServletTestCase
● Dal metodo testXXX si invoca il dispatching alla JSP
RequestDispatcher disp = config.getServletContext(). getRequestDispatcher("/pagina.jsp");disp.forward(request, response);
● Nel metodo endXXX si verifica l'output nella response
● Esistono però tool più specializzati
![Page 24: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/24.jpg)
Caso 2: TagLib
● Sono classi Java, che vivono in un contesto di pagina● Il testcase estende JspTestCase● Si utilizzano gli oggetti impliciti per inizializzare il test
● Si crea un'istanza del tag e le si passa l'oggetto implic. pageContext
● Si chiamano i metodi del CdV del tag– doStartTag(), doAfterBody(), doEndTag()...
● Si verifica che restituiscano il valore corretto
● Si controlla l'output (HTML, ...) del tag nel metodo endXXX()
![Page 25: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/25.jpg)
Caso 3: test logico
● Le JSP in genere utilizzano JavaBean creati dalle Servlet, che glieli passano attraverso la request. Perciò:
● Si estende JSPTestCase● Nel testXXX(), si creano tutti i bean necessari e si
mettono nella request.
● Si fa il forward alla JSP● Nel endXXX(), si controlla l'output
![Page 26: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/26.jpg)
Test e basi di dati
![Page 27: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/27.jpg)
Problemi
● Il test dei db, o con i db, è uno dei più complessi
● Il db è un'entità esterna– No codice Java. No refactoring...– Altri tool, altre interfacce, altre policy
● Il db è lento
● Il db è spesso condiviso– i test rischiano di sovrapporsi
● Il db è distribuito– Quali e quanti db testare?
● Il db è persistente– lo stato del db influisce sui test
![Page 28: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/28.jpg)
Considerazioni
● Un buon db test deve essere autosufficiente– non deve essere sensibile, nel bene o nel male, alle
modifiche al db effettuate da un altro test
● Un buon test crea tutti i dati che gli servono– il db deve essere inizializzato ad uno stato noto prima di
eseguire il test
● Serve quindi almeno un db completamente separato da quello di produzione
● Non è necessario che il test ripulisca il db quando ha terminato
● Non è necessario cancellare / creare tutto il db per ogni test
![Page 29: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/29.jpg)
“You need four databases”
● Un'organizzazione con quattro livelli di db consente un testing efficace
DEV
DEV
DEV
Integrazione Pre-produzione Produzione
![Page 30: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/30.jpg)
Level one: development
● Ogni sviluppatore dovrebbe avere un db a sua disposizione– Preferibilmente in locale
● Lo sviluppatore dovrebbe avere libertà totale su start/stop/manage della propria istanza
● I dati sono privi di utilità e significato pratico, se non per i test
● Il db può rimanere in uno stato inconsistente
● Per ragioni di efficienza, è preferibile utilizzare db lightweight– In-memory db (Hypersonic, Derby...)
![Page 31: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/31.jpg)
Level two: integration
● È il livello dove si eseguono i test d'integrazione e funzionali
● I responsabili sono sempre gli sviluppatori
● I dati sono ancora poco significativi
● Lo stato precedente del db non è significativo
● Le differenze di schema o errori vengono subito al pettine e vanno armonizzate
![Page 32: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/32.jpg)
Level three: pre-production
● Qui si testa l'ultima versione integrata funzionate, con dati (o partizioni di db) reali, provenienti dal db di produzione
● Prima dei test, il db va riallineato con la produzione
● La responsabilità di eseguire i test è del Q&A
● Non si fa integrazione.
● Test di carico e di accettazione
![Page 33: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/33.jpg)
Level four: production
● Dati reali
● Nessun testing qui!
![Page 34: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/34.jpg)
Java Db Testing
● Serve quindi qualcosa che semplifichi ed automatizzi il pià possibile:– lo start start/stop dell'istanza del db– le modifiche allo schema– l'immissione e la cancellazione dei valori d'inizializzazione– ripeta le operazioni precedenti per ogni test case
● Per aiutarci in questo, esiste DbUnit– basato su JUnit
![Page 35: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/35.jpg)
Caso tipico: Business Logic o Data Access Logic da testare● Approccio suggerito:
– Mantenere i dati di inizializzazione su file (xml, plain text, excel, ...) o hard coded
● Database In-Memory
● Inizializzare il db con dbUnit
● Invocare la logica da testare nel corpo del test
● Verificare il risultato:– verifica di comportamento della logica (può essere fatta
anche senza dbUnit, con un mock / stub!!)– verifica delle azioni compiute sul db
● sempre con dbUnit, o via codice con delle SELECT
![Page 36: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/36.jpg)
Importante
● NON concentrarsi a testare il framework di persistenza– Hibernate, iBatis....
● Il test è della propria applicazione, non di quelle degli altri
![Page 37: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/37.jpg)
Esercizi
● Testare una classe di business che scrive direttamente sul database
● La classe ha un metodo che legge un campo di una tabella e ne aggiorna il valore in base ad un criterio da lei stabilito (es: se maggiorenne pone il flag a Y)
● Esercizio 2:– Introdurre l'uso di un Data Access Object (DAO)– Testare anche il DAO
![Page 38: Java Unit Testing - In container and database testing](https://reader034.vdocumenti.com/reader034/viewer/2022042510/555e845dd8b42abd468b4efc/html5/thumbnails/38.jpg)
Licenza Creative Commons (sunto)
Attribuzione-Non commerciale-Condividi allo stesso modo
3.0 Unported
Tu sei libero di modificare, riprodurre, distribuire, comunicare al pubblico, esporre inpubblico, rappresentare, eseguire e recitare quest'opera.
Alle seguenti condizioni:
● Attribuzione. Devi attribuire la paternità dell'opera nei modi indicati dall'autore o da chi ti ha dato l'opera in licenza e in modo tale da non suggerire che essi avallino te o il modo in cui tu usi l'opera.
● Non commerciale. Non puoi usare quest'opera per fini commerciali.
● Condividi allo stesso modo. Se alteri o trasformi quest'opera, o se la usi per crearne un'altra, puoi distribuire l'opera risultante solo con una licenza identica o equivalente a questa.
● Testo completo della licenza completa su:http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode