PDA

View Full Version : Mock or not to Mock?


thebol
07-01-2007, 13:41
Ho provato a introdurre il TDD dove lavoro in piccoli componenti che dovevo modificare e per semplicità ( :asd: ) ho rifatto da zero. Questi componenti vengono usati da delle action di struts(per chi non le conosce delle servlet), e devono accedere a DB.

Si è posto il problema come usare l'accesso a db nei test. Ho deciso di Mockare l'accesso al db, e fin qua + o - tutto chiaro(anche se la soluzione non mi soddisfaceva + di tanto, forse sarebbe piu semplice un db in memory fatto apposta per i test...).

Però è sorto un problema. Dentro il componente creavo la connesione a db, cioè un oggetto(new DBConnect(...) ).

Problema:
Visto che io devo testare il componente, e questo crea l'oggetto che rappresenta la connesione al db, come faccio a dirgli di usare la connesione fake?

Naturalmente si può passare la connesione al componente come parametro(in creazione, o nel metodo che fa il lavoro).
Ma questo vuol dire che per testare un componente in pure isolation, questo non deve creare oggetti(o almeno oggetti che ne possono alterare il funzionamento, e che si prestano a essere mockati).

Questo crea problemi ad esempio, quando io voglio testare la action che usa il mio componente. La action ha la particolarità di essere chiamata dall'application server, percui non posso alterarne i parametri di creazione(a meno di fare cambiamenti strutturali che coinvolgerebbero tutte le action dell'applicazione)
In questo caso le soluzioni sarebbero 2:
La action usa il mio componente in una certa maniera, io mocko il mio componente e verifico che vengano effetuate le giuste chiamate con i giusti parametri. Questo non si può fare perchè il componente viene creato all'interno della action.

Oppure:
Mocko il db, e lo passo al mio componente. Non posso perchè la connesione al db o la crea il mio componente(che non posso mockare), oppure la passa la action al mio componente.Ma sto testando la action, e come faccio a dirgli di passare il db mockato invece di quello reale?


Il mock è percio molto utile quando qualcosa di complesso (il db, l'accesso ai file, alla rete, etc) viene passato a un componente, ma viene meno utile quando questo viene usato.

Certo nel mio esempio, si sarebbe potuto ristrutturare il meccansimo delle action, in modo da fare una action personalizzata a cui passare la connesione al db. Però nel mio caso era impossibile stando io testando solo una piccola parte dell'applicazione.

Tutto questo discorso per chiedervi o sentire opinioni sui mock, o meglio, su questa presunta (da me) limitiazione dei mock.





ps. Nel applicazione reale in un punto ho risolto il problema grazie al fatto che si usavano dei singletone. C'era un associazione stringa-> Classe per la connesione. Ho sostiutito la classe base, con quella mockata e ho risolto. Però in un altro punto non ci sono riuscito :|

pps so che il post è contorto, spero che qualcuno lo capisca :asd:

71104
07-01-2007, 14:04
hai scordato un "To" nel titolo :read:

PGI-Bis
07-01-2007, 14:30
Poichè ogni classe Java è caricata dinamicamente, potresti lasciare il codice inalterato e rimpiazzare la classe DBConnection "vera" con il suo mock attraverso il classpath.

Per sintetizzare in "jarrese", useresti i mock con:

java -cp .;Mocks.jar -jar Applicazione.jar

e i "real" con:

java -cp .;Reals.jar -jar Applicazione.jar

Mocks e Components conterrebbero due diversi DBConnection, uno mock e l'altro real, binariamente compatibili. Applicazione.jar sarebbe il pacchetto di tutto ciò che non è DBConnection ma eventualmente usi questa classe.

All'atto pratico il tutto è "facilmente" controllabile con i task di ant.

Non sono tuttavia sicuro che questo sia rigoroso dal punto di vista del TDD perchè usi una caratteristica che è propria di alcune specie di linguaggi, Java Smalltalk, Python, Ruby eccetera, ma non di altri, C++, C eccetera, limitazione che il TDD certamente non impone.

thebol
07-01-2007, 22:12
hai scordato un "To" nel titolo :read:cazz ero convinto che nel primo non ci andasse :asd: ma gugol ti da ragione :cry: