MockLib
http://mocklib.sourceforge.net/mocklib3/index.html
Apache License V2.0
JMockLib r3-1-1, February 11, 2009
08.11.2010
MockLib 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 MockLib zur Laufzeit erstellten Mock
untergeschoben. Da dieser Mock natürlich nicht die volle Programmlogik bietet, welche die ausprogrammierte Klasse einmal bieten soll, wird
innerhalb des TestCases definiert, wie der Mock auf genau diesen einen Fall reagieren soll. Ebenfalls können die der Mock-Methode übergebenen
Parameter abgefragt und überprüft werden, um so nicht nur das Ergebnis der zu testenden Methode, sondern auch den korrekten Methodenaufruf
zu prüfen.
MockLib ist komplexer zu bedienen, als es zu Beginn den Eindruck macht. Zahlreiche kleine und nur unzureichend dokumentierte Fallstricke
machen den Einstieg zäher und langwieriger als es sein müsste. Die gebotene Funktionalität ist dagegen gut. Zwar lassen sich nicht für
unterschiedliche Parameter der gleichen Mock-Methode unterschiedliche Werte zurückgeben, was an sich schade ist, doch weiß der restliche
Funktionsumfang, wie die abfragbaren Parameter, zu überzeugen. Beim Einsatz in kleinen Projekten muss abgewägt werden, ob es nicht einfacher
und schneller ist, die Methode welche fehlt, kurz zu implementieren, anstatt mit einem Mock zu emulieren. In größeren Projekten sollte sich der
zusätzliche Zeitaufwand aber schnell rechnen, da hier schon im vorhandenen Code Fehler identifiziert werden können, bevor das ganze Programm
fertig ist.
MockLib kann immer dann eingesetzt werden, wenn eine zu testende Methode auf eine weitere, noch nicht existente Methode, zugreift. Da MockLib
nicht nur einen Rückgabewert für den Mock festlegen, sondern auch die übergebenen Parameter ausgeben kann, lassen sich auch Methodenaufrufe
auf Korrektheit testen, die keinen Wert zurückgeben.
MockLib basiert auf JUnit und kann sich damit in alle Einsatzumgebungen einfügen, in denen auch JUnit arbeiten kann.
Das Werkzeug benötigt keine Installation. Es muss lediglich das Jar-File
heruntergeladen und in den BuildPath eingebunden werden, danach lässt sich MockLib benutzen.
Die Dokumentation ist die größte Schwachstelle von MockLib. Es existiert schlicht keine. Auf der Projektseite finden sich die JavaDoc API-Doku
und ein Satz zugegebenermaßen umfangreicher, kommentierter Beispiele, aber eine echte Anleitung fehlt leider vollständig. So ist man gezwungen, die
Beispiele Zeile für Zeile abzuarbeiten, um die hierbei gefundenen Konzepte auf eigenen Code zu übertragen, was nicht immer gut gelingt. Die
Kommentare innerhalb der Beispiele sind gerade so umfangreich, dass man nach längerem Studieren des Codes die Funktionsweise erkennen kann.
Hier wäre es wesentlich angenehmer gewesen, ein paar Seiten Fließtext zu den Beispielen zu schreiben, welche die Arbeitsweise von MockLib Schritt
für Schritt erklären.
Die Projektseite hat zumindest mit dem Release der neusten Version ein Update erfahren und scheint auch sonst immer wieder an den Stand der
aktuellen Version angepasst zu werden.
Das auf SourceForge gehostete Projekt nutzt die dort angebotenen Funktionen der Mailinglist sowie des Forums. Der Bugtracker ist zwar
ebenfalls aktiv, wird aber scheinbar nicht regelmäßig genutzt.
Die intuitive Nutzbarkeit ist einfach nicht gegeben. Die fehlende Doku macht es quasi unmöglich, schnell eine Funktion nachzuschlagen, es muss
jedes mal in den Codebeispielen gesucht werden, was mitunter sehr mühsam ist. Auch einzelne konzeptionelle Unschönheiten machen dem Neuanwender
das Leben schwer. So ist es z.B. recht seltsam, dass neu erstellte Mocks erst noch zum richtigen Typ hin gecastet werden müssen. Es muss mit
einiger Einarbeitungszeit gerechnet werden, bis MockLib produktiv eingesetzt werden kann.
Da MockLib auf JUnit basiert, kann es in gleichem Umfang automatisiert werden. Dem Einsatz in einem Ant-Skript steht somit nichts im Wege.
Die Automatisierung von MockLib ähnelt stark der Automatisierung von JUnit-Tests. Da MockLib 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. Dabei handelt es sich um das aktuelle Junit.jar und das aktuelle mocklib.jar. Zu dem verhält sich der Testablauf mit Hilfe des MockLib-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 Mocklib Testfälle ähnelt stark der Ausführung von JUnit-Testfällen. Der Mocklib-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 Mocklib-Bibliothek zugreifen, dies ist allerdings leicht mit Hilfe des <dependency>
-Elements realisiert. Davor muss die Mocklib-Bibliothek noch in das lokale Repository von Maven übertragen werden. Der folgenden Befehle erledigt diesen Aspekt:
mvn install:install-file -DgroupId=mocklib -DartifactId=mocklib -Dversion=3.0 -Dfile=mocklib3-r3-1-1.jar -Dpackaging=jar -DgeneratePom=true
Hierbei muss sich die Jar-Datei im aktuellen Ordner befinden und die Version ist an die aktuelle Nutzung anzupassen.
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
Im Vergleich des Aufwands liegen die beiden build-Werkzeuge circa gleich auf. Bei Maven muss zwar das benötigte JAR-Archiv noch in das lokale Repository gespeichert werden, allerdings ist dieser Aufwand auch nur einmalig da. Die Ausführung der einzelnen Tests wird dann mit Hilfe von JUnit-Testfällen vollzogen und ist somit leicht integrierbar.
Zuerst muss ein Mock aus einem gegebenen Interface heraus erstellt werden. Hierbei ist zu beachten, dass die Rückgabe nicht etwa ein Objekt vom
Typ des Interfaces ist, sondern ein MockObject, welches erst noch gecastet werden muss.
pi = MockObjectFactory.createMock(PiAusrechnen.class);
Mit addReturnValue() lässt sich der als String übergebenen Methode ein Rückgabewert zuordnen. Das geschieht nicht in Abhängigkeit
von dem übergebenen Parameter. Hier wird leider immer der gleiche Rückgabewert zurückgegeben:
pi.addReturnValue("calcPi",3.14);
Mit dem gecasteten Mock lässt sich nun die zu testenden Methode aufrufen:
k.flaeche(10, (PiAusrechnen)pi);
Mit getAllParams() lassen sich alle an die Mock-Methode übergebenen Parameter abfragen und überprüfen:
Object[] params = pi.expect("calcPi").getAllParams();
assertEquals(100, params[0]);
Die Klasse MyMocklibTest beinhaltet daraufhin folgenden Code:
package qsqs.mocklibtest;
import org.junit.Test;
import biz.xsoftware.mock.CalledMethod;
import biz.xsoftware.mock.MockObject;
import biz.xsoftware.mock.MockObjectFactory;
import qsqs.ueberdeckungen.Kreis;
import qsqs.ueberdeckungen.PiAusrechnen;
import junit.framework.TestCase;
public class MyMocklibTest extends TestCase {
private MockObject pi;
private Kreis k;
@Override
protected void setUp() throws Exception {
pi = MockObjectFactory.createMock(PiAusrechnen.class);
k=new Kreis();
}
@Test
public void testUmfang() throws Exception {
pi.addReturnValue("calcPi",3.14);
assertEquals(10*2*3.14,k.umfang(10, (PiAusrechnen)pi));
Object[] params = pi.expect("calcPi").getAllParams();
assertEquals(100, params[0]);
}
@Test
public void testFlaeche() throws Exception {
pi.addReturnValue("calcPi",3.14);
assertEquals(10*10*3.14,k.flaeche(10, (PiAusrechnen)pi));
Object[] params = pi.expect("calcPi").getAllParams();
assertEquals(1000, params[0]);
}
}
Das komplette Beispiel steht ebenfalls als fertiges Eclipse-Projekt zum Download bereit.
Der MockLib-Test kann anschließend als JUnit-Test ausgeführt werden und es öffnet sich die gewohnte JUnit-Ansicht mit den
Testergebnissen des Testlaufs:
Nur über Analyse der Beispiele der Webseite möglich.
keine
Zurück zur Werkzeugübersicht
Zurück zur CSI-Hauptseite