# Unit Testing mit JMock



## Stefan2902 (6. Aug 2009)

Hallo,

ich habe mich nun schon geraume Zeit damit beschäftigt, mich in Unit Testing mit JMock einzuarbeiten. Insbesondere habe ich mir die Getting Started tutorials (z.b. jMock - Getting Started) oder auch (Enterprise Java Community: Using JMock in Test Driven Development) angesehen.

Da ich noch relativ neu im Java Umfeld unterwegs bin, frage ich mich ob jemand eine einfache Step-by-Step Anleitung für einen Unit Test unter JMock kennt. Es würde mir schon reichen, eine Klasse zu testen, die eine beliebige Zeichenkette sendet und einen festen String durch ein Mockobjekt zurück erhält.

In allen o.g. Beispielen ist mir nie klar, welche Klasse eigentlich getestet wird und was dasa eigentliche Mock Objekt ist?

Hat jemand eine Idee?

Stefan


----------



## maki (6. Aug 2009)

> In allen o.g. Beispielen ist mir nie klar, welche Klasse eigentlich getestet wird und was dasa eigentliche Mock Objekt ist?
> 
> Hat jemand eine Idee?


Ähm.. ja: Man testet niemals Mocks 

Zeig doch mal deine Klasse die du Testen möchtest.


----------



## Stefan2902 (10. Aug 2009)

Vielen Dank. Du hast vollkommen recht. 

Ich werde das Unit testing nun mit JUnit machen. Daher ist die Überschrift falsch.

Jedoch würde  emich interessieren, wie manin Objekt/Klasse mit JMock simulieren kann.

Ein ganz einfaches Bsp. wäre prima. Z.b. ich habe eine Klasse, die den String "Hallo" an eine gemockte Klasse sendet. Als Rückgabe würde ich gern den String "World" erhalten.

Gruß
Stefan


----------



## maki (10. Aug 2009)

maki hat gesagt.:


> Zeig doch mal deine Klasse die du Testen möchtest.




Also, wo ist der Code der getestet werden soll?
Dann sieht man recht schnell ob Mocks Sinn ergeben oder nicht.


----------



## bygones (10. Aug 2009)

man nutzt Mocks um eben seine Units testen zu koennen.

Beim Unit testing geht es darum, seinen zu testenden Code (SUT = System under Test) in Isolation zu testen - um diese Isolation zu bekommen nutzt man u.a. eben mocks.

mal von wikipedia kopiert

Konkret sind Mock-Objekte sinnvoll, wenn das „echte“ Objekt

    * nicht deterministische Ergebnisse liefert (z. B. die aktuelle Uhrzeit oder die aktuelle Temperatur);
    * Schwierigkeiten bei der Vorbereitung oder während der Ausführung bereitet (z. B. beim Testen von Benutzungsoberflächen);
    * Verhalten zeigen soll, das nur schwer auszulösen ist (z. B. einen Netzwerkfehler);
    * langsam ist (z. B. eine vollständige Datenbank, die vor dem Test erst initialisiert werden müsste);
    * noch nicht existiert (z. B. in größeren Software- oder Hardware-Entwicklungsprojekten);
    * Informationen und Methoden ausschließlich zu Testzwecken (und nicht für seine eigentliche Aufgabe) zur Verfügung stellen müsste.




Stefan2902 hat gesagt.:


> Ein ganz einfaches Bsp. wäre prima. Z.b. ich habe eine Klasse, die den String "Hallo" an eine gemockte Klasse sendet. Als Rückgabe würde ich gern den String "World" erhalten.


qie Maki schon schrieb - bei mocks muss man immer aufpassen, was man nun mockt ... man laeuft gern gefahr alles wegzumocken bzw seine mocks dann zu testen etc.

die Frage klingt schon sehr merkwuerdig fuer einen mock... daher ist es wohl sinnvoller du zeigst den code


----------



## Stefan2902 (10. Aug 2009)

Alles klar.

Hier der Code:


```
package com.eet.lexifi;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;

/**
 * A simple demo of Xalan 1. This code was originally written using Xalan 1.2.2.
 * It will not work with Xalan 2.
 */

public class XMLtoCSV {

	/**   fgfd
	 * Accept two command line arguments: the name of an XML file, and the name
	 * of an XSLT stylesheet. The result of the transformation is written to
	 * stdout.
	 */
	public static void main(String[] args) throws Exception {
		if (args.length != 2) {
			System.err.println("Usage: java Transform [xmlfile] [xsltfile]");
			System.exit(1);
		}

		File xmlFile = new File(args[0]);
		File xsltFile = new File(args[1]);

		// JAXP liest Daten über die Source-Schnittstelle
		Source xmlSource = new StreamSource(xmlFile);
		Source xsltSource = new StreamSource(xsltFile);
		
		// das Factory-Pattern unterstützt verschiedene XSLT-Prozessoren
		TransformerFactory transFact = TransformerFactory.newInstance();	
		
		Transformer trans = transFact.newTransformer(xsltSource);
		
		trans.transform(xmlSource, new StreamResult(System.out));

	}
}
```

Diese Klasse nutzt XLST, um aus einer XML Datei gewisse Informationen zu extrahieren und in eine CSV Datei auszugeben.

Das Ergebnis CSV stream (siehe letzte Zeile) wird z.Zt. auf die Console ausgegeben. Ich möchte diesen Stream jedoch an eine Applikation senden, die basierend auf diesen Daten einen Wert generiert und zurückliefert. Leider ist die Applikation noch nicht produktiv (nicht vohanden). Daher würde ich Sie gern simulieren bzw. mocken.

Gruß
Stefan


----------



## bygones (10. Aug 2009)

Da bringt mocken nicht viel imho.

was willst du eigentlich testen ? dass das Ergebnis angezeigt wird ? oder dass die konvertierung klappt ?

wenn die anzeige dann waere es toerricht die zu mocken, da du dann das was du testen willst mockst.

PS: achso du willst eine Funktionalitaet der GUI testen... 

auch waere der ansatz falsch, da du dann den zu testenden Code mockst


----------



## Stefan2902 (10. Aug 2009)

Also vielleicht noch ein paar Worte zum Gesamtziel.

Ich habe diese Klasse, die aus einer XML Datei mittels XSLT eine CSV Datei generiert.

Im produktiven Betrieb soll dies ein Adapter sein/werden, der

a) von einer produktiven Applikation (z.zt. nicht vorhanden) eine XML Datei entgegen nimmt

b) die CSV Outputdatei an eine weitere Applikation weitergibt und einen errechneten Wert zurückerhält.

Da weder die Inputapplikation noch die Outputapplikation z.Zt. vorhanden sind, möchte ich diese Applikationen mocken/simulieren, um für eine Art "Proof of Concept" durchzuführen.

Ich habe ein wenig im Internet recherchiert und dachte, dass es sinnvoll wäre, nicht vorhandene Applikationen durch Mocks zu ersetzen. Weiterhin habe ich gelesen, dass in diesem Zusammenhang "Design by Interface" eine Rolle spielt. Ich habe gehofft, dass man mit diesen Methoden Interfaces und Mocks baut, sodass ich sukzessive die simulierten Applikationen durch die echten ersetzen kann.

Ich hoffe ich habe jetzt nicht zu vier durcheinander gebracht.

Gruß
Stefan


----------



## bygones (10. Aug 2009)

Stefan2902 hat gesagt.:


> Also vielleicht noch ein paar Worte zum Gesamtziel.
> 
> Ich habe diese Klasse, die aus einer XML Datei mittels XSLT eine CSV Datei generiert.
> 
> ...



ok wenn ich es richtig verstehen hast du folgendes:

1. Applikation bekommt XML Datei
2. Applikation erstellt CSV ueber XSLT
3. naechste Applikation bekommt CSV und berechnet irgendwas

???

ich gehe mal davon aus, dass du nicht Applikationscode mit dem Umwandeln vereinheitlichst (wenn wir von einer GUI sprechen..), ergo muss es eine Funktionalitaet geben, die diese Berechnung anstellt - UND die muss getestet werden.
Wenn es spaeter dann eine GUI gibt nutzt diese die Funktionalitaet und erschafft keine eigene, ergo musst du die Funktionalitaet testen udn nicht die GUI.

allein von der Beschreibung wie ich sie versteh brauchst du hier gar keine mocks... 



Stefan2902 hat gesagt.:


> Ich habe ein wenig im Internet recherchiert und dachte, dass es sinnvoll wäre, nicht vorhandene Applikationen durch Mocks zu ersetzen. Weiterhin habe ich gelesen, dass in diesem Zusammenhang "Design by Interface" eine Rolle spielt. Ich habe gehofft, dass man mit diesen Methoden Interfaces und Mocks baut, sodass ich sukzessive die simulierten Applikationen durch die echten ersetzen kann.


es ist schon richtig dass man mocks einsetzen kann wenn es eine Funktionalitaet noch nicht existiert - aber nach deiner Beschreibung von oben klang es so als willst du das mocken, was du eigentlich testen willst.

mocks dienen nicht als Platzhalter fuer eine schrittweise Implementierung....

"Design by Interface" spielt eine wichtige Rolle - jegliche Implementierung sollte nicht auf der eigentlichen Implementierung arbeiten, sondern immer die Abstraktion erhalten


----------



## Stefan2902 (10. Aug 2009)

Die fehlenden Komponenten / Applikationen sind für mich Black-Boxen. Es handelt sich hierbei wirklich, um seperate Applikationen, deren Funktionalität ich !nicht! testen möchte.

Der Datenaustausch mit diesen Applikationen erfolgt über Fileshares. Daher geht es einzig und allein darum, diese Blackboxen zu simulieren. Am besten, indem ich das Konzept des Design by Interface berücksichtige.

Jemand eine Idee/Anregung oder Beispiel, wie ich das umsetzen kann?


----------



## bygones (10. Aug 2009)

Stefan2902 hat gesagt.:


> Die fehlenden Komponenten / Applikationen sind für mich Black-Boxen. Es handelt sich hierbei wirklich, um seperate Applikationen, deren Funktionalität ich !nicht! testen möchte.


ok soweit klar



Stefan2902 hat gesagt.:


> Der Datenaustausch mit diesen Applikationen erfolgt über Fileshares. Daher geht es einzig und allein darum, diese Blackboxen zu simulieren. Am besten, indem ich das Konzept des Design by Interface berücksichtige.


ich versteh immer noch nicht warum du die nicht vorhandenen Applikation simulieren willst (nochmal - reden wir von Applikation im allgemeinen oder von einer GUI ?). 
Wenn du eine Funktionalitaet hast die es zu testen gilt (in deinem Fall _zuruecklieferen der Werte xyz aus einem CSV_) so brauchst du den Code real, um zu testen zu koennen.
In welchem Kontext dieser Code dann steckt ist fuer den Test der Funktionalitaet irrelevant...


----------



## Stefan2902 (10. Aug 2009)

> ich versteh immer noch nicht warum du die nicht vorhandenen Applikation simulieren willst (nochmal - reden wir von Applikation im allgemeinen oder von einer GUI ?).



Es handelt sich um 3rd Party Applikationen bzw. (out-of the box) Applikationen, die man per Setup installiert und auf deren Code / Funktionalität keinen Einfluss habe. 




> Wenn du eine Funktionalitaet hast die es zu testen gilt (in deinem Fall zuruecklieferen der Werte xyz aus einem CSV) so brauchst du den Code real, um zu testen zu koennen.
> In welchem Kontext dieser Code dann steckt ist fuer den Test der Funktionalitaet irrelevant...



Eigentlich möchte ich gar keine Funktionalität testen!

Im Rahmen des Proof of Concepts werden die errechneten Werte (siehe Resultat der Auswertung vom CSV file) für eine gewisse Zeit vom Kunden weiterverwendet auch wenn die produktiven Applikationen noch nicht vorhanden sind. Die Datenqualität spielt dabei erstmal keine große Rolle.

Das Gesamtsystem soll simuliert werden. Sukzessive sollen dann die Mocks durch dir produktiven Anwendungen ersetzt werden.


----------

