Aggiornamento settembre 2019: l'unico framework beffardo supportato (per impostazione predefinita) da Spring Boot è Mockito . Se usi Spring, la risposta è abbastanza ovvia.
Direi che la competizione è tra JMockit e PowerMock , poi Mockito .
Lascerei jMock ed EasyMock "semplici" perché usano solo proxy e CGLIB e non usano strumentazione Java 5 come i framework più recenti.
jMock inoltre non ha avuto una versione stabile per oltre 4 anni. jMock 2.6.0 ha richiesto 2 anni per passare da RC1 a RC2, e poi altri 2 anni prima che fosse effettivamente rilasciato.
Per quanto riguarda Proxy e CGLIB vs strumentazione:
(EasyMock e jMock) sono basati su java.lang.reflect.Proxy, che richiede l'implementazione di un'interfaccia. Inoltre, supportano la creazione di oggetti fittizi per le classi tramite la generazione di sottoclassi CGLIB. Per questo motivo, dette classi non possono essere finali e solo i metodi di istanza sovrascrivibili possono essere derisi. La cosa più importante, tuttavia, quando si utilizzano questi strumenti le dipendenze del codice sotto test (cioè, gli oggetti di altre classi da cui dipende una data classe sotto test) devono essere controllate dai test, in modo che le istanze fittizie possano essere passate ai client di quelle dipendenze. Pertanto, le dipendenze non possono essere semplicemente istanziate con il nuovo operatore in una classe client per la quale si desidera scrivere unit test.
In definitiva, i limiti tecnici degli strumenti di derisione convenzionali impongono le seguenti limitazioni di progettazione al codice di produzione:
- Ogni classe che potrebbe dover essere derisa in un test deve implementare un'interfaccia separata o non essere definitiva.
- Le dipendenze di ogni classe da testare devono essere ottenute tramite metodi di creazione di istanze configurabili (factory o un Service Locator) o essere esposte per l'inserimento delle dipendenze. In caso contrario, gli unit test non saranno in grado di passare implementazioni fittizie di dipendenze all'unità sottoposta a test.
- Poiché solo i metodi di istanza possono essere derisi, le classi da sottoporre a test unitario non possono chiamare alcun metodo statico sulle loro dipendenze, né istanziarle utilizzando uno dei costruttori.
Quanto sopra è stato copiato da http://jmockit.org/about.html . Inoltre, confronta se stesso (JMockit), PowerMock e Mockito in diversi modi:
Ora ci sono altri strumenti di derisione per Java che superano anche i limiti di quelli convenzionali, tra cui PowerMock, jEasyTest e MockInject. Quello che si avvicina di più al set di funzionalità di JMockit è PowerMock, quindi lo valuterò brevemente qui (inoltre, gli altri due sono più limitati e non sembrano più essere sviluppati attivamente).
JMockit contro PowerMock
- Prima di tutto, PowerMock non fornisce un'API completa per il mocking, ma funziona invece come un'estensione di un altro strumento, che attualmente può essere EasyMock o Mockito. Questo è ovviamente un vantaggio per gli utenti esistenti di questi strumenti.
- JMockit, d'altra parte, fornisce API completamente nuove, sebbene la sua API principale (Expectations) sia simile sia a EasyMock che a jMock. Sebbene ciò crei una curva di apprendimento più lunga, consente anche a JMockit di fornire un'API più semplice, più coerente e più facile da usare.
- Rispetto all'API JMockit Expectations, l'API PowerMock è più "di basso livello", costringendo gli utenti a capire e specificare quali classi devono essere preparate per il test (con l'annotazione @PrepareForTest ({ClassA.class, ...}) ) e che richiedono chiamate API specifiche per gestire vari tipi di costrutti del linguaggio che possono essere presenti nel codice di produzione: metodi statici (mockStatic (ClassA.class)), costruttori (sopprimere (costruttore (ClassXyz.class))), invocazioni di costruttori ( waitNew (AClass.class)), mock parziali (createPartialMock (ClassX.class, "methodToMock")), ecc.
- Con JMockit Expectations, tutti i tipi di metodi e costruttori vengono derisi in modo puramente dichiarativo, con derisione parziale specificata tramite espressioni regolari nell'annotazione @Mocked o semplicemente "un-mocking" dei membri senza aspettative registrate; cioè, lo sviluppatore dichiara semplicemente alcuni "campi fittizi" condivisi per la classe di test, o alcuni "campi fittizi locali" e / o "parametri fittizi" per i metodi di prova individuali (e in quest'ultimo caso l'annotazione @Mocked spesso non essere necessario).
- Alcune funzionalità disponibili in JMockit, come il supporto per derisione di uguali e hashCode, metodi sostituiti e altri, non sono attualmente supportate in PowerMock. Inoltre, non esiste alcun equivalente alla capacità di JMockit di acquisire istanze e simulare implementazioni di tipi di base specificati durante l'esecuzione del test, senza che il codice del test stesso abbia alcuna conoscenza delle effettive classi di implementazione.
- PowerMock utilizza caricatori di classi personalizzati (di solito uno per classe di test) per generare versioni modificate delle classi derise. Un uso così intenso di programmi di caricamento classi personalizzati può portare a conflitti con librerie di terze parti, da qui la necessità di utilizzare a volte l'annotazione @PowerMockIgnore ("package.to.be.ignored") sulle classi di test.
- Il meccanismo utilizzato da JMockit (strumentazione runtime tramite un "agente Java") è più semplice e sicuro, sebbene richieda il passaggio di un parametro "-javaagent" alla JVM durante lo sviluppo su JDK 1.5; su JDK 1.6+ (che può essere sempre utilizzato per lo sviluppo, anche se distribuito su una versione precedente) non esiste tale requisito, poiché JMockit può caricare in modo trasparente l'agente Java su richiesta utilizzando l'API di collegamento.
Un altro strumento di derisione recente è Mockito. Sebbene non tenti di superare i limiti dei vecchi strumenti (jMock, EasyMock), introduce un nuovo stile di test del comportamento con i mock. JMockit supporta anche questo stile alternativo, tramite l'API Verifications.
JMockit contro Mockito
- Mockito si basa su chiamate esplicite alla sua API per separare il codice tra le fasi di registrazione (quando (...)) e di verifica (verifica (...)). Ciò significa che qualsiasi invocazione a un oggetto fittizio nel codice di test richiederà anche una chiamata all'API fittizia. Inoltre, questo spesso porterà a chiamate ripetitive quando (...) e verificate (simulate) ....
- Con JMockit, non esistono chiamate simili. Certo, abbiamo le nuove chiamate ai costruttori NonStrictExpectations () e Verifications (), ma si verificano solo una volta per test (in genere) e sono completamente separate dalle invocazioni a metodi e costruttori derisi.
- L'API Mockito contiene diverse incongruenze nella sintassi utilizzata per le chiamate ai metodi derisi. Nella fase di registrazione, abbiamo chiamate come when (mock.mockedMethod (args)) ... mentre nella fase di verifica questa stessa chiamata verrà scritta come verify (mock) .mockedMethod (args). Si noti che nel primo caso l'invocazione a mockedMethod viene effettuata direttamente sull'oggetto mock, mentre nel secondo caso viene effettuata sull'oggetto restituito da verify (mock).
- JMockit non presenta tali incongruenze perché le invocazioni ai metodi fittizi vengono sempre effettuate direttamente sulle istanze fittizie stesse. (Con una sola eccezione: per abbinare le invocazioni sulla stessa istanza derisa, viene utilizzata una chiamata onInstance (mock), risultando in codice come onInstance (mock) .mockedMethod (args); la maggior parte dei test non avrà bisogno di usarlo, però. )
- Proprio come altri strumenti di derisione che si basano sul concatenamento / avvolgimento di metodi, Mockito si imbatte anche in una sintassi incoerente durante lo stubbing dei metodi void. Ad esempio, scrivi when (mockedList.get (1)). ThenThrow (new RuntimeException ()); per un metodo non void e doThrow (new RuntimeException ()). when (mockedList) .clear (); per uno vuoto. Con JMockit, è sempre la stessa sintassi: mockedList.clear (); risultato = new RuntimeException () ;.
- Un'altra incongruenza si verifica nell'uso delle spie Mockito: "beffe" che consentono di eseguire i metodi reali sull'istanza spiata. Ad esempio, se spy fa riferimento a un elenco vuoto, invece di scrivere when (spy.get (0)). ThenReturn ("foo") dovrai scrivere doReturn ("foo"). When (spy) .get ( 0). Con JMockit, la funzionalità di mocking dinamico fornisce funzionalità simili alle spie, ma senza questo problema poiché i metodi reali vengono eseguiti solo durante la fase di riproduzione.
- In EasyMock e jMock, le prime API mocking per Java, l'attenzione era interamente sulla registrazione di invocazioni attese di metodi mocked, per oggetti mock che (per impostazione predefinita) non consentono invocazioni impreviste. Tali API forniscono anche la registrazione delle chiamate consentite per oggetti fittizi che consentono chiamate impreviste, ma questa è stata considerata una funzionalità di seconda classe. Inoltre, con questi strumenti non c'è modo di verificare esplicitamente le invocazioni ai mock dopo che il codice sotto test è stato esercitato. Tutte queste verifiche vengono eseguite in modo implicito e automatico.
- In Mockito (e anche in Unitils Mock), viene preso il punto di vista opposto. Tutte le invocazioni per falsificare oggetti che possono accadere durante il test, registrate o meno, sono consentite, mai previste. La verifica viene eseguita esplicitamente dopo aver esercitato il codice sotto test, mai automaticamente.
- Entrambi gli approcci sono troppo estremi e di conseguenza non ottimali. JMockit Expectations & Verifications è l'unica API che consente allo sviluppatore di scegliere senza problemi la migliore combinazione di invocazioni fittizie rigorose (previste per impostazione predefinita) e non rigorose (consentite per impostazione predefinita) per ogni test.
- Per essere più chiari, l'API Mockito presenta il seguente difetto. Se è necessario verificare che durante il test si sia verificata un'invocazione a un metodo mocked non void, ma il test richiede un valore restituito da quel metodo diverso da quello predefinito per il tipo restituito, il test Mockito avrà codice duplicato: una chiamata when (mock.someMethod ()). thenReturn (xyz) nella fase di registrazione e una verifica (mock) .someMethod () nella fase di verifica. Con JMockit è sempre possibile registrare un'aspettativa rigorosa, che non dovrà essere verificata esplicitamente. In alternativa, è possibile specificare un vincolo di conteggio delle chiamate (volte = 1) per qualsiasi aspettativa non rigorosa registrata (con Mockito tali vincoli possono essere specificati solo in una chiamata di verifica (mock, vincolo)).
- Mockito ha una sintassi scadente per le verifiche in ordine e per le verifiche complete (ovvero controllare che tutte le invocazioni agli oggetti fittizi siano verificate esplicitamente). Nel primo caso, è necessario creare un oggetto aggiuntivo e su di esso vengono effettuate chiamate per la verifica: InOrder inOrder = inOrder (mock1, mock2, ...). Nel secondo caso, devono essere effettuate chiamate come verifyNoMoreInteractions (mock) o verifyZeroInteractions (mock1, mock2).
- Con JMockit, scrivi semplicemente new VerificationsInOrder () o new FullVerifications () invece di new Verifications () (o new FullVerificationsInOrder () per combinare entrambi i requisiti). Non è necessario specificare quali oggetti fittizi sono coinvolti. Nessuna chiamata API beffarda extra. E come bonus, chiamando unverifiedInvocations () all'interno di un blocco di verifica ordinato, puoi eseguire verifiche relative agli ordini che sono semplicemente impossibili in Mockito.
Infine, JMockit Testing Toolkit ha una portata più ampia e obiettivi più ambiziosi rispetto ad altri toolkit di simulazione, al fine di fornire una soluzione di test per sviluppatori completa e sofisticata. Una buona API per il mocking, anche senza limitazioni artificiali, non è sufficiente per la creazione produttiva di test. È essenziale anche uno strumento di Code Coverage indipendente dall'IDE, facile da usare e ben integrato, ed è ciò che JMockit Coverage mira a fornire. Un altro pezzo del set di strumenti di test per sviluppatori che diventerà più utile con l'aumentare delle dimensioni della suite di test è la capacità di rieseguire in modo incrementale i test dopo una modifica localizzata al codice di produzione; anche questo è incluso nello strumento Copertura.
(concesso, la fonte potrebbe essere parziale, ma beh ...)
Direi di andare con JMockit . È il più facile da usare, flessibile e funziona praticamente per tutti i casi, anche quelli difficili e gli scenari in cui non puoi controllare la classe da testare (o non puoi romperla per motivi di compatibilità, ecc.).
Le mie esperienze con JMockit sono state molto positive.