Mocking di un modulo di utilità per il test dell'unità? [duplicare]

4

Sto scrivendo unit test per una classe che fa uso di un modulo di utilità generale. In generale, voglio prendere in giro tutte le dipendenze della classe, ma prendere in giro alcune delle funzioni di utilità sembra strano. Alcuni di essi sono semplici funzioni per gestire percorsi di file, manipolazione di stringhe, ecc. E sembra un dettaglio di implementazione che la classe in prova utilizza questa utility per implementare la sua API pubblica. Se il codice è stato refactored per non aver bisogno di quella funzione di utilità, non mi interessa e preferirei che il test non fallisse.

Il problema è che alcune delle funzioni di utilità dipendono dal filesystem, e ovviamente devono essere prese in giro. Quindi sto considerando uno dei due

  1. Lasciando il modulo di utilità così com'è e prendendo in giro il modulo del filesystem
  2. O utilizzando la maggior parte del modulo delle utility ma prendendo in giro le singole funzioni che hanno dipendenze sul filesystem

Che cosa hanno fatto gli altri in questo scenario?

    
posta Rob Lourens 30.11.2015 - 02:46
fonte

2 risposte

5

Dipende da ciò che consideri una "unità". Alcune persone pensano che un'unità da testare dovrebbe essere la parte più piccola in cui possono essere ridotte le cose -, cioè, solo la funzione sotto test con tutto ciò che dipende da una derisione. Penso che questo stia spingendo troppo le cose verso l'ideologia di un sogno utopico di test unitario.

Un'unità dovrebbe essere una semplice parte del tuo programma che sia facile da testare, senza essere troppo grande da diventare un test di mini-integrazione. Per molte persone questo significa la classe, e molti (incluso Martin Fowler) sostengono che alcune classi dipendenti siano incluse in quella definizione. Quindi una classe di utilità di wrapper I / O di file sarebbe perfettamente adatta per essere considerata parte dell'unità sottoposta a test.

Quindi spetta a te decidere in che modo granulare prendere il tuo sistema per i test. Se pensate che il vostro modulo di filesystem funzioni bene (e sia stato testato da solo forse), includetelo semplicemente e prendete il (molto piccolo) rischio che possa causare il fallimento della vostra funzione di test (che non è una cosa negativa come potete questo - che è ciò che prova è tutto). Ciò potrebbe significare che impieghi molto meno tempo a scrivere test rispetto a quello che risolvi eventuali potenziali bug riscontrati durante il test della tua funzione.

    
risposta data 30.11.2015 - 10:23
fonte
3

In general I want to mock all the dependencies of the class

Penso che sia dove hai preso la svolta sbagliata. Se una classe ha delle dipendenze, allora queste dipendenze devono mai essere derise nel test per quella classe; questo rende il test senza valore. Se ciò significa che il test per quella classe non è un test unitario, allora così sia. Non è possibile eseguire un test isolato stand-alone per qualcosa che non sia indipendente e isolato.

Il mocking è per quando un oggetto ha collaboratori o output di qualche tipo sconosciuto (ad esempio, in genere la classe corrispondente ha un campo che è di tipo astratto o di interfaccia).

Ad esempio, supponi di avere:

Puoisimulare(oaltrimentispegnere)FileBugRepositoryduranteiltestdiBugService,perchénonèunadipendenzastaticadiclasse,solounapossibiledisposizionedioggettiinfasediesecuzione.MaquandoproviFileBugRepository,nondovrestisimulareFileUtilsperchévieneutilizzatodirettamenteedèl'unicaimplementazionevalida.

Inquestocaso,FileUtilsèunadipendenzastaticadiretta;nellamaggiorpartedellelingueilcodicediFileBugRepositoryconterràilnomeFileUtils.Quindinonpuoitestarloconqualcos'altrosenzausarequalchemagiadibassolivelloperridefinireilcodicechestaitestandoperesserequalcosadidiversodaquellocheè.

Questaèovviamentelastradadapercorrere,migliaiaditestconcoperturaelevata,costidimanutenzioneelevatienessunvaloreaggiunto,enonavereunabuonarispostaalladomanda"perché non stai prendendo in giro Integer e String"?

Il principio generale vale anche se il codice è scritto usando l'anti-pattern dove ogni classe ha un'interfaccia separata, cioè IFileUtils e FileUtilsImpl ; quindi IFileUtils è semplicemente un alias per FileUtilsImpl.

    
risposta data 30.11.2015 - 12:50
fonte

Leggi altre domande sui tag