Best practice per la copertura del codice dei metodi di interfaccia vuoti

3

Data una classe che implementa un'interfaccia, ma non ha bisogno di tutti i metodi implementati, qual è la best practice per il test di unità di questa classe rispetto alla copertura del codice? - o è considerato un segno per un odore di codice?

Per rendere il problema più concreto, considera una classe Java (la domanda non è limitata a Java) che implementa ComponentListener ma deriva da qualche X (in modo da escludere la scelta di utilizzare ComponentAdapter ) . La classe è tuttavia interessata solo al metodo componentResized() e lascia gli altri corpi del metodo di callback vuoti.

Quando si controlla la copertura del codice, viene visualizzato un report che indica correttamente che i restanti metodi non sono stati testati. Per ovvi motivi, esito ad aggiungere un test che chiama semplicemente un metodo no-op per ragioni di copertura.

Anche se non sono obbligato a raggiungere una certa copertura, continuo a pensare che, di per sé, questo fenomeno possa indicare un odore di codice rispetto al principio della responsabilità unica. D'altra parte, non è inverosimile che una rappresentazione componente sia responsabile dell'aggiornamento del suo stato su un ridimensionamento.

Esiste una sorta di consenso o best practice su come gestire tali metodi, o la domanda è illegittima in quanto in esso è il risultato di un disegno apparentemente cattivo?

    
posta Frank 11.09.2013 - 11:18
fonte

5 risposte

6

Non sono sicuro di quale sarebbe la migliore pratica se non fosse per me, il tuo problema non è un problema di metodi di interfaccia vuoti - è un problema che le tue interfacce sono sbagliate.

Se si implementa un'interfaccia, implementare l'intera interfaccia - se l'interfaccia è troppo ampia o ha funzionalità a cui non si è interessati, dividere l'interfaccia e fare in modo che l'interfaccia principale implementi le sotto-interfacce e fare in modo che il componente esegua solo la parte bit appropriato.

    
risposta data 11.09.2013 - 11:26
fonte
2

Un'interfaccia rappresenta un contratto che la classe di implementazione accetta di soddisfare. Le parti di quel contratto che non ti interessano, stai ancora implementando e quindi hanno ancora un comportamento - il comportamento non fa nulla (come mi aspetto nel tuo esempio) o non lancia un UnsupportedOperationException se stai riducendo l'ambito dell'implementazione (come List#Clear ).

Penso che sia ancora importante a) documentare la mancanza di implementazione, b) aggiungere test per convalidare l'implementazione in modo che quando qualcuno arriva e lo cambi, i test si interrompono e devono pensare un po 'prima di modificare la IOnlyCareAboutResizedComponentsListener class.

    
risposta data 11.09.2013 - 11:45
fonte
1

Scriverò un test per l'interfaccia, che chiama tutti i metodi e ignora i risultati (solo per verificare se non sono state generate eccezioni o metodi). Di quanto tu possa rendere la tua classe di test estendere questa classe di test dell'interfaccia.

In questo modo ottieni una copertura completa.

    
risposta data 11.09.2013 - 11:30
fonte
1

La risposta di Michael condivide la mia sensazione che si tratti di un odore di design in primo luogo.

Se si tratta di un callback vuoto che viene richiamato in fase di esecuzione, è necessario scrivere il test per assicurarsi che non accada nulla in quel metodo.

Se il metodo non è implementato e non deve mai essere chiamato, dovresti considerare di lanciare un java.lang.UnsupportedOperationException .

    
risposta data 11.09.2013 - 11:46
fonte
-1

Penso che uno schema migliore se hai bisogno di copertura del codice sta usando una fabbrica astratta. La differenza tra interfacce e classi astratte ha già avuto qualche discussione su questo sito. Trovo questa spiegazione la più pertinente per la tua domanda.

Le classi / metodi astratti sono obsoleti?

    
risposta data 11.09.2013 - 16:59
fonte

Leggi altre domande sui tag