2010-01-12 5 views
11

Il mio team di sviluppo ha iniziato a utilizzare Mockito e ha classi definite come "final". Ho letto in Java efficace di Joshua Bloch e nel thread SO When to use final che tutte le classi dovrebbero utilizzare il modificatore finale. Ci sono stati alcuni disaccordi nella discussione, ma sono d'accordo con l'idea di forzare la composizione della classe a meno che l'eredità abbia un senso.Cosa fare quando Java Best Practices è in conflitto con Mockito

Cosa devo fare quando voglio testare le classi utilizzando un framework di test come Mockito che richiede alle classi di non avere il modificatore 'finale'? Spero che qualcun altro abbia riscontrato problemi simili durante il loro sviluppo. Su quali risoluzioni è arrivato il tuo team di sviluppo?

Ci sono due risposte ovvie come usare JMock o rimuovere il modificatore 'finale' sulle classi che vogliamo testare, ma vogliamo restare con un framework di test esterno (oltre a JUnit) e potrebbe essere difficile convincere altri sviluppatori per rimuovere il modificatore 'finale'.

Grazie.

+4

Fare tutte le * classi * 'final' di certo non è una buona pratica ... è passato un po 'di tempo dall'ultima lettura di Effective Java, ma il consenso del thread collegato non sembra implicare che sia. Dovresti contrassegnare le classi 'final' per indicare che c'è qualche ragione per cui non dovrebbero essere estese - se non c'è motivo, aggiunge solo la complessità non necessaria - come hai trovato. Inoltre, se ti rendi conto che hai bisogno di estendere la classe da qualche parte lungo la strada, devi cambiare il codice della classe originale per scrivere la nuova classe - violando il principio Aperto/Chiuso. – Nate

risposta

10

Cosa serve più:

  1. La capacità di fare in modo che qualcuno non eredita dalla classe, O
  2. La capacità di fare in modo che il codice è testabile usare il quadro di scherno di scelta?

In generale, credo che non c'è bisogno di far rispettare (1). Per me, testability (2), è molto più importante. Cosa si adatta meglio alla tua situazione?

+0

La testabilità è molto più importante IMHO e io crediamo che si adatti alla nostra situazione. – austen

+1

Non è necessario sacrificare il design per motivi di "testabilità". Puoi averli entrambi, semplicemente usando lo strumento giusto per il lavoro.In questo caso, utilizzare uno degli strumenti di simulazione Java che possono simulare i metodi e le classi finali: JMockit (il mio strumento) o PowerMock (che supporta l'API Mockito, quindi non è necessario riscrivere completamente i test esistenti). –

4

Se vuoi che le tue classi siano definitive, puoi farle implementare le interfacce. Le interfacce sono irrisolvibili.

4

Come già accennato nell'altra risposta è possibile effettuare le classi finali per implementare l'interfaccia e nei test simulare l'interfaccia o le interfacce.

Questo è uno dei vantaggi dell'utilizzo di oggetti Mock; in scenari come questo ti fanno pensare a come il codice può essere meglio organizzato. Se il tuo codice base ha molto riferimento alle classi finali (quindi vincolanti per l'implementazione concreta) viola il principio OO di "programmazione su un'interfaccia" e la necessità di una migliore testabilità ti aiuterà a pensare al refactoring per eliminare la dipendenza dalle implementazioni concrete.

Questo documento sull'uso di Mock Objects Endo-testing: Unit Testing with Mock Objects ha una sezione (4.4) dal titolo scoperta interfaccia che spiega come finto oggetti aiutano a scoprire le interfacce.

+0

Mi piace l'idea della scoperta dell'interfaccia. – austen

+3

Quando scrivo codice che utilizza una classe finale e questa classe non implementa un'interfaccia separata, non * sto * violando il principio di "programma su un'interfaccia, non un'implementazione" di GoF. Il principio * non * richiede che ogni classe implementa un'interfaccia separata. Altre parti del libro GoF lo rendono chiaro, per coloro che sono disposti a leggerlo. –

Problemi correlati