Qual è il miglior framework per creare oggetti finti in Java? Perché? Quali sono i pro e i contro di ciascun framework?
Qual è il miglior framework per creare oggetti finti in Java? Perché? Quali sono i pro e i contro di ciascun framework?
Risposte:
Ho avuto un buon successo usando Mockito .
Quando ho provato a conoscere JMock ed EasyMock, ho scoperto che la curva di apprendimento era un po 'ripida (anche se forse sono solo io).
Mi piace Mockito per la sua sintassi semplice e pulita che sono stato in grado di cogliere abbastanza rapidamente. La sintassi minima è progettata per supportare molto bene i casi comuni, anche se le poche volte in cui ho dovuto fare qualcosa di più complicato ho scoperto che ciò che volevo era supportato e facile da comprendere.
Ecco un esempio (abbreviato) dalla homepage di Mockito:
import static org.mockito.Mockito.*;
List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();
Non è molto più semplice di così.
L'unico aspetto negativo principale che mi viene in mente è che non deriderà i metodi statici.
Sono il creatore di PowerMock, quindi ovviamente devo raccomandarlo! :-)
PowerMock estende sia EasyMock che Mockito con la possibilità di deridere metodi statici , finali e persino privati. Il supporto EasyMock è completo, ma il plug-in Mockito richiede un po 'più di lavoro. Stiamo programmando di aggiungere anche il supporto JMock.
PowerMock non è destinato a sostituire altri framework, ma può essere utilizzato nelle situazioni difficili in cui altri framework non consentono il derisione. PowerMock contiene anche altre utili funzionalità come la soppressione di inizializzatori e costruttori statici .
Il sito del progetto JMockit contiene molte informazioni comparative per gli attuali kit di strumenti di simulazione.
In particolare, controlla la matrice di confronto delle funzionalità , che copre EasyMock, jMock, Mockito, Unitils Mock, PowerMock e ovviamente JMockit. Cerco di mantenerlo il più possibile accurato e aggiornato.
Ho avuto successo con JMockit .
È piuttosto nuovo, quindi è un po 'grezzo e poco documentato. Utilizza ASM per ridefinire dinamicamente il bytecode della classe, in modo da poter deridere tutti i metodi inclusi statici, privati, costruttori e inizializzatori statici. Per esempio:
import mockit.Mockit;
...
Mockit.redefineMethods(MyClassWithStaticInit.class,
MyReplacementClass.class);
...
class MyReplacementClass {
public void $init() {...} // replace default constructor
public static void $clinit{...} // replace static initializer
public static void myStatic{...} // replace static method
// etc...
}
Ha un'interfaccia Expectations che consente anche scenari di registrazione / riproduzione:
import mockit.Expectations;
import org.testng.annotations.Test;
public class ExpecationsTest {
private MyClass obj;
@Test
public void testFoo() {
new Expectations(true) {
MyClass c;
{
obj = c;
invokeReturning(c.getFoo("foo", false), "bas");
}
};
assert "bas".equals(obj.getFoo("foo", false));
Expectations.assertSatisfied();
}
public static class MyClass {
public String getFoo(String str, boolean bool) {
if (bool) {
return "foo";
} else {
return "bar";
}
}
}
}
Il rovescio della medaglia è che richiede Java 5/6.
Puoi anche dare un'occhiata ai test usando Groovy. In Groovy puoi facilmente deridere le interfacce Java usando l'operatore 'as':
def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest
Oltre a questa funzionalità di base, Groovy offre molto di più sul fronte beffardo, compresi i potenti MockFor
e le StubFor
classi.
Ho iniziato a usare i mock con EasyMock . Abbastanza facile da capire, ma il passaggio di replay è stato piuttosto fastidioso. Mockito lo rimuove, ha anche una sintassi più pulita in quanto sembra che la leggibilità fosse uno dei suoi obiettivi principali. Non posso sottolineare abbastanza quanto sia importante, dal momento che la maggior parte degli sviluppatori passerà il loro tempo a leggere e mantenere il codice esistente, non a crearlo.
Un'altra cosa interessante è che le interfacce e le classi di implementazione sono gestite allo stesso modo, diversamente da EasyMock dove è ancora necessario ricordare (e controllare) di utilizzare un'estensione di classe EasyMock.
Ho dato una rapida occhiata a JMockit recente e, sebbene l'elenco delle funzioni della lavanderia sia piuttosto completo, penso che il prezzo sia leggibilità del codice risultante e che debba scrivere di più.
Per me, Mockito colpisce il punto debole, essendo facile da scrivere e leggere e gestire la maggior parte delle situazioni che la maggior parte del codice richiederà. Usare Mockito con PowerMock sarebbe la mia scelta.
Una cosa da considerare è che lo strumento che sceglieresti se stessi sviluppando da solo, o in un piccolo team affiatato, potrebbe non essere il migliore da ottenere per una grande azienda con sviluppatori di diversi livelli di abilità. La leggibilità, la facilità d'uso e la semplicità richiederebbero maggiore considerazione in quest'ultimo caso. Non ha senso ottenere il quadro beffardo definitivo se molte persone finiscono per non usarlo o non mantenere i test.
Stiamo usando pesantemente EasyMock e EasyMock Class Extension al lavoro e ne siamo abbastanza soddisfatti. Fondamentalmente ti dà tutto ciò di cui hai bisogno. Dai un'occhiata alla documentazione, c'è un bell'esempio che mostra tutte le funzionalità di EasyMock.
Ho usato JMock presto. Ho provato Mockito nel mio ultimo progetto e mi è piaciuto. Più conciso, più pulito. PowerMock copre tutte le esigenze assenti in Mockito, come deridere un codice statico, deridere la creazione di un'istanza, deridere classi e metodi finali. Quindi ho tutto ciò che mi serve per svolgere il mio lavoro.
Mi piace JMock perché sei in grado di creare aspettative. Questo è totalmente diverso dal verificare se un metodo è stato chiamato trovato in alcune librerie simulate. Utilizzando JMock puoi scrivere aspettative molto sofisticate. Guarda il trucco cheat jmock .
Sì, Mockito è un ottimo framework. Lo uso insieme a hamcrest e Google Guice per impostare i miei test.
La migliore soluzione per deridere è che la macchina faccia tutto il lavoro con test automatici basati su specifiche. Per Java, vedere ScalaCheck e il framework Reductio inclusi nella libreria Functional Java . Con i framework di test automatizzati basati su specifiche, si fornisce una specifica del metodo sotto test (una proprietà su di esso che dovrebbe essere vera) e il framework genera test e oggetti finti automaticamente.
Ad esempio, la seguente proprietà verifica il metodo Math.sqrt per vedere se la radice quadrata di qualsiasi numero positivo n al quadrato è uguale a n.
val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }
Quando chiami propSqrt.check()
, ScalaCheck genera centinaia di numeri interi e controlla la tua proprietà per ognuno, assicurandosi anche automaticamente che i casi limite siano coperti bene.
Anche se ScalaCheck è scritto in Scala e richiede il compilatore Scala, è facile testare il codice Java con esso. Il framework Reductio in Functional Java è una pura implementazione Java degli stessi concetti.
Mockito offre anche la possibilità di metodi di stub, argomenti corrispondenti (come anyInt () e anyString ()), verificando il numero di invocazioni (times (3), atLeastOnce (), never ()) e altro .
Ho anche scoperto che Mockito è semplice e pulito .
Una cosa che non mi piace di Mockito è che non puoi stub dei metodi statici .
Per qualcosa di un po 'diverso, potresti usare JRuby e Mocha che sono combinati in JtestR per scrivere test per il tuo codice Java in Ruby espressivo e succinto. Ci sono alcuni esempi beffardi utili con JtestR qui . Un vantaggio di questo approccio è che prendere in giro classi concrete è molto semplice.
Ho iniziato a usare i mock tramite JMock, ma alla fine sono passato a usare EasyMock. EasyMock era proprio questo, più semplice, e forniva una sintassi più naturale. Non ho cambiato da allora.