EasyMock
http://www.easymock.org/
MIT License
Version 2.4 mit JUnit 4.4
08.11.2010
EasyMock erlaubt es Methoden zu testen, die auf noch nicht ausprogrammierte Klassen zugreifen. Hierbei muss die zu testende Methode anstatt
einer Klasse ein Interface erwarten. Anstatt einer ausprogrammierten Klasse bekommt sie dann einen mit EasyMock zur Laufzeit erstellten Mock
untergeschoben. Da dieser Mock natürlich nicht die volle Programmlogik bietet, welche die ausprogrammierte Klasse später einmal
bieten soll, wird innerhalb des TestCases definiert, wie der Mock auf genau diesen einen Fall reagieren soll. Ebenfalls lässt sich mit
EasyMock testen, ob der Aufruf der Mockmethode überhaupt stattgefunden hat, so dass hier schon Programmierfehler aufgespürt werden
können.
EasyMock hält was der Name verspricht: Ein einfach zu nutzendes Werkzeug zur Erstellung von Mocks. Der Funktionsumfang beschränkt
sich hierbei auf die Kernkompetenzen ohne unnötiges Beiwerk. Durch die gute Doku und das einfache und durchgängig umgesetzte Konzept
geht der Einstieg schnell von statten. Für den Einsatz in kleinen Projekten bleibt aber abzuwägen, ob wirklich ein Mock-Werkzeug zum
Einsatz kommen muss. Hier kann es eventuell schneller sein, einfach die fehlende Methode/Klasse zu implementieren, als einen Test über
einen Mock zu verwirklichen. Für große Projekte mit vielen Entwicklern und eventuell sogar einer eigenen Mannschaft, die sich nur
um das Qualitätsmanagement kümmert ist EasyMock dagegen wie geschaffen. Mit JUnit als Basis skaliert es auch für große
Projekte sehr gut und kann ohne größere Umstände in schon vorhandene Projekte eingebunden werden. Die Aktualität sorgt
dabei für eine hohe Kompatibilität zu aktuellen Entwicklungswerkzeugen.
EasyMock kann immer dort zum Einsatz kommen wo Klassen/Methoden zum Test von anderen Klassen/Methoden benötigt werden, welche aber noch
nicht fertig ausprogrammiert sind. Dabei ist es egal, ob es sich um funktionelle Klassen, welche ein Ergebnis berechnen, oder um Bestandteile
einer GUI handelt.
EasyMock basiert auf JUnit 4.1 und kann sich damit in alle Einsatzumgebungen einfügen in denen auch JUnit arbeiten kann.
EasyMock muss nicht speziell installiert werden. Es genügt, das Java-Archiv herunter zu laden,
zu entpacken und die Bibliothek "easymock.jar" in den Buildpath der jeweiligen IDE hinzuzufügen. Zusätzlich wird eventuell noch JUnit
4.x benötigt, welches hier gefunden werden kann
und ebenfalls in den Buildpath integriert werden muss.
Eclipse: Projekt -> Properties -> Java Build Path -> Add external Jar -> easymock.jar auswählen
Netbeans: Projekt -> Properties -> Libraries -> Add Jar -> easymock.jar auswählen
Die Dokumentation von EasyMock ist neben Englisch auch in Französisch vorhanden in zwei Teile untergliedert, die Anwenderdokumentation,
welche als Fließtext vorliegt und anhand vieler Beispiele die Nutzung von EasyMock erklärt, sowie die JavaDoc API Dokumentation,
welche nur in Englisch verfügbar ist.
Die Anwenderdokumentation ist leicht verständlich, setzt aber Grundwissen im Bereich JUnit und Softwarequalität voraus. Die Beispiele
sind gut und erklären einfach und verständlich, wie das Werkzeug zu benutzen ist. Der einzige Kritikpunkt ist, dass die in den
Beispielen verwendeten Klassen- und Methodennamen zum Teil verlauten lassen, dass sie Teil der Libary sind, obwohl sie zum Test gehören.
Die API Dokumentation ist leider nicht so gut gelungen wie die Anwenderdokumentation. Es gibt noch etliche Methoden, zu denen kein JavaDoc existiert.
Hier wäre es besser gewesen, wenn man sich direkt in der benutzten IDE anzeigen lassen könnte, welche Funktionalität die Methode
bietet und was diese erwartet. Da sich das Werkzeug noch in der Weiterentwicklung befindet, kann sich dieser Punkt durchaus noch bessern.
Die Projektseite ist vom Juli 2008 und damit zusammen mit der letzten Aktualisierung von EasyMock erschienen. Das Projekt scheint sich noch
in Entwicklung zu befinden, was darauf hoffen lässt, dass es auch noch an kommende Versionen von Java und JUnit angepasst wird.
Das Projekt bietet dem Nutzer eine Yahoo!Group, über welche Kontakt mit den Entwicklern aufgenommen werden kann. Obwohl das Projekt bei
SourceForge gehostet ist, werden die SourceForge-Funktionalitäten wie Mailinglist oder Forum nicht genutzt. Der Bugtracker ist zwar aktiv,
allerdings wird er von den Entwicklern ebenfalls nicht genutzt.
Die Einarbeitung in EasyMock geht nicht zuletzt wegen der guten und beispielreichen Dokumentation schnell von Statten. In wenigen Minuten hat
man die Funktionsweise begriffen und ist in der Lage, das Werkzeug im Projektumfeld einzusetzen. Dass die Methoden tun was ihr Name verspricht,
beschleunigt die Einarbeitung nochmals.
Da EasyMock in JUnit-Testfällen zum Einsatz kommt, kann es von der umfangreichen Automatisierung von JUnit profitieren. Die Integration
ist dadurch genauso gegeben wie der Einsatz in einem Ant-Skript.
Die Automatisierung von EasyMock ähnelt stark der Automatisierung von JUnit-Tests. Da EasyMock auch das JUnit-Framework verwendet, müssen keine großen Änderungen vorgenommen werden, falls ein JUnit-Testablauf mit Hilfe von Ant definiert wurde. Zum Kompilieren der Sourcen müssen allerdings weitere externe Bibliotheken eingebunden werden. Zur Vollständigkeit sei diesen nochmal aufgelistet:
- asm.jar
- cglib-2.2.jar
- cglib-2.2.jar
- junit-4.8.2.jar
Zu dem verhält sich der Testablauf mit Hilfe des EasyMock-Frameworks gleich mit dem Ablauf von normalen JUnit-Tests. Dadurch können die vorhanden Features eines JUnit-Testablaufs wie z. B. die automatische Report-Generierung genutzt werden.
Eine Beispielautomatisierung ist hier zu finden.
Die Automatisierung der EasyMock Testfälle ähnelt stark der Ausführung von JUnit-Testfällen. Der EasyMock-Testfall wird in diesem Szenario durch einen JUnit-Testfall angestoßen und ist somit für den Maven-Prozess nicht direkt relevant. Die Sourcen müssen zwar beim Kompilieren und bei der Ausführung auf die EasyMock-Bibliotheken zugreifen, dies ist allerdings leicht mit Hilfe des <dependency>
-Elements realisiert. EasyMock bietet ein fertiges Plugin zur Einbindung in das Maven-Skript an. Dazu muss die pom.xml nur um das folgende Dependency-Element erweitert werden:
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.0</version>
</dependency>
Die benötigten EasyMock-Bibliotheken werden dann automatisch von dem Maven-Repository heruntergeladen.
Die Ausführung des Tests ähnelt somit stark der Ausführung eines normalen JUnit-Testfalls. Durch den Aufruf mvn test
wird der Testfall angestoßen und ausgeführt. Die Ergebnisse lassen sich dann im Target
-Verzeichnis finden.
Ein einfaches Automatisierungsbeispiel ist hier zu finden.
Vergleich Ant und Maven
Der Aufwand der beiden build-Werkzeuge ist circa der gleiche. Maven bietet schon ein fertiges Plugin das über das dependency
-Element leicht eingebunden werden kann. Bei Ant müssen die benötigten Jar-Archive manuell eingebunden werden. Allerdings bietet Ant hingegen wiederum die Verwendung von Pattern-Sets an. Diese ermöglichen dem Benutzer zum Beispiel alle Dateien aus einem bestimmten Ordner mit einzubinden. Dadurch sinkt der manuelle Aufwand von Ant wiederum.
Ziel des einführenden Beispiels ist es, die Funktions- und Implementationsweise von Mocks anhand eines einfachen und leicht
nachvollziehbaren Beispiels aufzuzeigen.
Zur sinnvollen Verwendung von Mocks wird ein Interface benötigt, dessen Methoden noch
implementiert werden müssen. Dazu wird in diesem Beispiel das Interface IMockMe genutzt, welches
den Rückgabwert von Pi bis zu einer der Funktion übergegeben Genauigkeit und die Bearbeitung eines Strings
bereitstellt:
public interface IMockMe {
public double Pi(int precision);
public void addString(String addMe);
}
Nun wird eine Klasse benötigt, welche auf die Methoden des Interfaces zurückgreift:
public class MockMeImplemented{
/* Benutzt die nicht implementierte Interfacemethode addString(String addMe); */
public void addStringtoList(String addMe,IMockMe pie){
pie.addString(addMe);
}
/* Benutzt die nicht implementierte Interfacemethode Pi(int precision); */
public double returnPI(int precision,IMockMe pi){
return pi.Pi(precision);
}
}
Da EasyMock hauptsächlich auf statische Methoden setzt, muss zu Beginn das Paket entsprechend eingebunden werden:
import static org.easymock.EasyMock.*;
Zur Durchführung der Tests wird jeweils ein Objekt von MockMeImplemented
und IMockMe
benötigt.
Nach der Erstellung muss dem Interface mittels mock = createMock(IMockMe.class);
ein Mock zugewiesen werden.
private IMockMe mock;
private MockMeImplemented piImp;
@Before
public void setUp(){
mock = createMock(IMockMe.class);
piImp = new MockMeImplemented();
}
Nach der Erstellung des Mocks folgt die Aufnahme und Wiedergabe des Testverhaltens.
Die Aufnahme erfolgt bis zum Aufruf der Methode replay();
. So wird
in folgendem Codeausschnitt der Aufruf der Interfacemethode mock.addString("i");
aufgenommen und
mittels replay(mock);
wiedergegeben.
Nach dem Umschalten in den Wiedergabemodus kann überprüft werden, ob das
Verhalten von addStingtoList
korrekt ist.
Zudem wird automatisch geprüft, ob die Übergabeparameter mit denen der "gemockten" Methode übereinstimmen.
verify(mock);
stellt sicher, dass die angegeben Methoden auch tatsächlich ausgeführt wurden:
@Test
public void expectedAddSomethig(){
mock.addString("i");
replay(mock);
piImp.addStringtoList("i", mock);
verify(mock);
}
Wird verify(mock);
nicht verwendet, würde auch dieser Fall den Testdurchlauf bestehen:
@Test
public void expectedAddSomethig2(){
mock.addString("i");
replay(mock);
}
In diesem Fall wird die Mockfunktionalität mit JUnit kombiniert, um den Rückgabewert von piImp.returnPI();
zu überprüfen.
Mit expect(mock.Pi(100)).andReturn((double)3.14);
wird angegeben, welcher Wert von der Methode Pi();
zurückgegeben werden soll.
Da returnPI();
die unimplementierte Methode Pi();
aufruft, wird der übergebene Wert des Mocks verwendet.
Durch assertEquals();
wird getestet, ob der erwartete Wert mit dem tatsächlichen Wert übereinstimmt.
@Test
public void expectedValuePi(){
expect(mock.Pi(100)).andReturn((double)3.14);
replay(mock);
assertEquals(3.14, piImp.returnPI(100,mock), 0);
verify(mock);
}
Die geschriebenen Testfälle lassen sich einfach über Rechtsklick auf die Testklasse -> Run as -> JUnit ausführen.
Die Auswertung folgt nach dem bekannten JUnit-Stil. Grüne Testfälle zeigen bestandene, rot markierte Testfälle nicht
bestandene Tests.
Zudem wird ein "Failure Trace" angezeigt, dem genauere Informationen über den Testfehlschlag entnommen werden können.
In diesem Fall wurde der Methodenaufruf Pi();
mit einem unerwarteten Parameter aufgerufen.
Das komplette Beispiel steht ebenfalls zum Download bereit:
[EasyMock-Test.tar.gz]
Die EasyMock-Dokumentation auf der Projektseite.
keine
Zurück zur Werkzeugübersicht
Zurück zur CSI-Hauptseite