Java: Va bene abusare dei bean Spring (@Component) piuttosto che usare classi di utilità finali statiche?

4

Sono combattuto tra l'utilizzo di DI e le classi di utilità statiche sul mio codice.

Attualmente ho creato una classe statica DateUtil che deve essere acceduta solo in modo statico. Questa classe è responsabile della sola creazione e manipolazione delle date utilizzando una varietà di librerie con assolutamente nessuna dipendenza esterna di terze parti.

Tutto sembra a posto, ma ora il testing delle unità diventa più complicato, poiché ora dobbiamo usare PowerMockito per stubare correttamente il comportamento della classe statica.

Al contrario, se avessi rimosso l'staticità di DateUtil e convertito in Spring @Component, ora i test unitari possono essere un po 'più semplici, tuttavia, ora abbiamo tutte queste dipendenze ovunque e non lo sono certo che questo è lo scopo dei fagioli gestiti da Spring.

Come dovrei procedere con questo? Va bene usare i bean Spring ovunque e dimenticarsi del tutto del codice statico? Va bene abusare delle capacità DI di Spring? Quando è "troppo DI"?

    
posta mpmp 07.02.2018 - 20:51
fonte

2 risposte

4

L'ipotesi prevalente che i metodi statici non siano testabili da unità sembra essere sorta dagli sviluppatori che sono abituati a scrivere test unitari contro istanze istanziabili di classe, e tutte le cose che vengono con mock, stub, interfacce, dipendenze injection, ecc. Non puoi fare nulla di ciò con le classi statiche. Tuttavia ...

I metodi statici che operano su (più o meno) tipi primitivi come Date non richiedono nulla di tutto ciò. Supponendo che i metodi statici siano puri (ovvero non contengano effetti collaterali ed evitino lo stato statico), è possibile testarli semplicemente chiamandoli con un valore di test e asserendo il risultato corretto.

Questo è tutto. Fare qualsiasi altra cosa annegherà i tuoi colleghi programmatori in un inutile mare di complessità senza alcun ulteriore vantaggio.

Le classi non statiche hanno uno scopo molto specifico. Se hai bisogno di questo scopo, usa assolutamente uno. Ma se non ne hai bisogno, perché usarlo se la tua unica motivazione è che non puoi applicare le tue solite tecniche di test di classe? Il rimedio è imparare una tecnica di prova più adatta, non calzare il metodo in prova in una classe solo perché pensi di aver bisogno di un contenitore per testarlo.

Ulteriori letture
È statico universalmente "malvagio" per il test delle unità e, in tal caso, perché fa il Resharper lo consiglio?

    
risposta data 07.02.2018 - 21:20
fonte
3

Ecco la mia regola empirica. Utilizzare le classi di utilità statiche se i metodi sono solo 1-2 righe ed eseguire operazioni facili da nominare con una o due parole e che è molto improbabile che possano mai cambiare. Quindi, ad esempio Math.max(double, double) rende un ottimo metodo di utilità statica come MoreObjects.firstNonNull(Object...) .

Dato che la definizione di ciò che questi metodi fanno è molto improbabile da cambiare, è anche bene prendere in considerazione il loro comportamento quando si testano altre classi che fanno uso di questi metodi. Se provi il tuo metodo che usa Math.max() , non provi a stubare il comportamento di Math.max() , vero? Si potrebbe obiettare che in questo modo il test non è in realtà un test unitario, ma a chi importa. Se il tuo metodo utilizza un metodo di String class, provi a smantellare quel comportamento? Non avrebbe alcun senso.

Se i criteri sopra indicati non sono soddisfatti, preferisco il DI normale. Quindi, nel caso delle date, se le operazioni sono qualcosa come firstMondayAfter(Date) , una classe di utilità statica dovrebbe essere completamente soddisfacente. Se fosse più simile a getStartOfMyCompanyFiscalYear(Date) , andrei con DI.

    
risposta data 07.02.2018 - 21:26
fonte

Leggi altre domande sui tag