|
|
|
|||
Mock Creator Version 0.2.4 |
||||
Home Kontakt Kompetenz Projekte MockCreator Eclipse 2 VisualAge 4 Standalone Version 0.1 Download Xpedition Impressum Feedback![]() ![]() ![]() ![]()
|
Juli 2003:
Der Mock Creator wurde ursprünglich von Christian Junghans bei abstrakt entwickelt. Er dient dazu in Java Mockobjekte aus Interfaces zu generieren. Er ist verfügbar für
"frühere" News
26. August 2002
12. August 2002
08. August 2002
MailinglisteDiskussionen, Feedback und Bugreports bitte an die Mailingliste auf Sourceforge Der Mockcreator ist freie Software, wir übernehmen keine Garantie für irgendwelche Probleme die sich aus seiner Nutzung ergeben. Selbstverständlich helfen wir aber gern bei Fragen und Problemen. Was sind MockObjekte?MockObjekte dienen dem isolierten (Unit-)Test von Komponenten und Klassen. Sie "simulieren" Objekte, die in einem Test verwendet werden. Dieser Artikel führt nur in die Bedienung und Installation des MockCreators ein - er liefert keine Einführung in die Arbeit mit MockObjects. Eine diesbezügliche Dokumentation befindet sich z.B. unter www.mockobjects.com. Schnittstelle der generierten MockObjekteHier ein Beispiel für generierte Mockobjekte für das Interface Foo: public interface Foo {
String doSomething( String something );
double squareRoot( double input );
}
Hier die generierte Klasse: public class MockFoo extends de.abstrakt.mock.MockObject implements Foo {
// Methoden aus dem Interface Foo
public String doSomething( java.lang.String something ) {...}
public double squareRoot( double input ) {...}
// setup MockObject: Setzen der Erwartungen,
// ggf. mit Rückgabewert oder zu werfender Exception.
public void expectDoSomething( String something, String returnValue ) {...}
public void expectDoSomething( String something, Throwable throwable ) {...}
public void expectSquareRoot( double input, double returnValue ) {...}
public void expectSquareRoot( double input, Throwable throwable ) {...}
// setup MockObject: Angegebene Methoden bei Aufruf nicht beachten.
// ggf. mit Rückgabewert oder zu werfender Exception.
public void setDoSomethingDummy( Throwable throwable ) {...}
public void setDoSomethingDummy( String returnValue ) {...}
public void setSquareRootDummy( Throwable throwable ) {...}
public void setSquareRootDummy( double returnValue ) {...}
}
Wichtige geerbte Methoden aus de.abstrakt.mock.MockObject: package de.abstrakt.mock;
public class MockObject {
public void startBlock() {...}
public void endBlock() {...}
public void verify() {...}
public Boolean checkDummy( Boolean flag, boolean value ) {...}
[...]
}
Einfache VerwendungDer Mock Creator erstellt Mockobjekte, die das gewählte Interface implementieren. Im Test werden die Aufrufe die auf den Mockobjekten erwartet werden in folgender Form angegeben. Wir erwarten in diesem Fall, dass auf einem Object Foo die Methode doSomething mit dem Parameter "nobody expects" aufgerufen wird. Als Folge dieses Aufrufs gibt das MockObject das Ergebnis "the spanish inquisition" zurück. Wird hingegen squareRoot(...) oder doSomething mit einem anderen Parameter aufgerufen, so wirft MockFoo eine Exception. // setup des MockObjects MockFoo mockFoo = new MockFoo(); mockFoo.expectDoSomething( "nobody expects", "the spanish inquisition" ); // Testcode aus der Testklasse assertEquals( "the spanish inquisition", mockFoo.doSomething( "nobodyExpects" ) ); // Verifizierung mockFoo.verify(); Erweiterte FeaturesDurch die Verwendung von MockObjects in Tests sowie die einfache Verfügbarkeit von MockImplementationen ist es sehr einfach möglich, Tests zu schreiben, die eine Änderung des zu testenden Codes massiv erschweren - schliesslich schreiben die Mockobjekte jeden einzelnen Aufruf genau vor. Hier gibt es mehrere Abhilfen... wir raten dazu, alle zu verwenden :-)
MockObjects vorsichtig einsetzenWahrscheinlich muss jeder einmal die Schwierigkeiten durchlaufen haben, Mock-getesteten Code umzuschreiben (refaktorisieren) um dieses Problem auch selbst zu sehen... ;-) Dummyaufrufe parametrisierenDie vom MockCreator generierten Klassen ermöglichen es, einige Aufrufe als "unerheblich für den Testverlauf" zu kennzeichnen - ein guter Kandidat hierfür sind beispielsweise einfache getXY-Methoden. Dadurch wird der tatsächliche Aufruf dieser Methoden nicht überwacht: // setup für das MockObject
MockCustomer mockCustomer = new MockCustomer();
mockCustomer.setDummyGetName( "Otto Normalverbraucher" );
mockCustomer.expectGetBalance( new Money( 10 ) );
// Erzeugen der zu testenden Klasse und Test
ThisClassIsTested testee = new ThisClassIsTested( mockCustomer );
testee.thisMethodIsTested();
// Testcode aus der zu testenden Klasse
public class ThisClassIsTested {
private Customer _customer;
public ThisClassIsTested( Customer customer ) { _customer = customer; }
public void thisMethodIsTested() {
doSomething( _customer.getName() );
doSomethingElse( _customer.getName() );
Money balance = _customer.getBalance();
System.out.println( "Balance for Customer " + _customer.getName()
+ ": " + balance + " Euro" );
}
[...]
}
// Verifizierung
mockCustomer.verify();
Blöcke von Code in beliebiger ReihenfolgeDas Standardverhalten der generierten MockObjects ist, dass die Reihenfolge der Methodenaufrufe beachtet wird. Es ist jedoch möglich, dieses Standardverhalten zu ändern - und zwar auch für einzelne "Methodenblöcke": // setup für das MockObject
MockFoo mockFoo = new MockFoo();
mockFoo.expectDoSomething( "nobody expects", "the spanish inquisition" );
mockFoo.startBlock();
mockFoo.expectSquareRoot( 4, 2 );
mockFoo.expectSquareRoot( 9, 3 );
mockFoo.expectSquareRoot( 16, 4 );
mockFoo.endBlock();
// Testcode aus der Testklasse
// Testcode aus der zu testenden Klasse
public class ThisClassIsTested {
private Foo _foo;
public ThisClassIsTested( Foo foo ) { _foo = foo; };
public void thisMethodIsTested() {
_foo.doSomething( "nobody expects" ) );
System.out.println( "sqrt(16) is " + _foo.squareRoot( 16 ) );
System.out.println( "sqrt(4) is " + _foo.squareRoot( 4 ) );
System.out.println( "sqrt(9) is " + _foo.squareRoot( 9 ) );
}
[...]
}
// Verifizierung
mockFoo.verify();
Generierte Objekte in KürzeJeder Aufruf einer expect-Methode (hier expectGet) speichert ein Objekt-Array mit Methodenname und Paramaetern in einer ExpectationList -> mockobjects und den Rückgabewert (hier "Eintrag 1") in eine Liste von Rückgabewerten. Jeder Methodenaufruf vom zu testenden Objekt auf dem Mockobjekt vergleicht den Aufruf mit dem zuvor im Test als erwartet angegebenen Aufruf. Um auch Fehlerfälle testen zu können generiert der MockCreator zu jeder Methode im Interface zwei expect-Methoden in der folgenden Form (hier für die Methode "methodCall"): public void expectMethodName
( [alle Parameter]
[, Rückgabewert sofern
nicht void]
);
public void expectMethodName
( [alle Parameter]
[, Throwable der bei Aufruf
geworfen wird]
);
Mit Hilfe der zweiten Version ist es möglich, auch einen Fehlerfall im Test zu simulieren. Die Mock-Implementation gibt in diesem Fall bei Aufruf keinen Rückgabewert zurück, sondern löst die übergebene Exception aus. Hierbei ist die Schnittstelle zu beachten: Sofern nicht im Interface eine Exception deklariert ist, können hier nur RuntimeExceptions und Errors angegeben werden, da sonst während des Tests eine ClassCastException auftritt. Wenn das Interface Exceptions deklariert, können natürlich auch die deklarierten Exceptions als Werte für den Parameter Throwable verwendet werden. Wenn die Anzahl von Methodenaufrufen auf einem Objekt unerheblich ist, dient ein Aufruf der setDummyXY-Methoden dem Festlegen der entsprechenden Rückkabewerte bei Aufruf der Methode. public void setDummyMethodCall( [Rückgabewert sofern nicht void] ); public void setDummyMethodCall( [Throwable, der bei Aufruf geworfen wird] ); Blöcke von Code, deren Aufrufreihenfolge unerheblich ist, lassen sich mit startBlock und endBlock festlegen. public void startBlock(); public void endBlock(); Features
Geplante Features für nächste Releases
Lasst uns doch wissen welche davon ihr für sinnvoll haltet oder was ihr sonst vermisst Support, KontaktDer Mockcreator ist freie Software, wir übernehmen keine Garantie für irgendwelche Probleme die sich aus seiner Nutzung ergeben. Selbstverständlich helfen wir aber gern bei Fragen und Problemen. Kontakt, Feedback und Bugreports bitte über die Mailingliste auf Sourceforge Bekannte Schwierigkeiten, offene Punkte
Lizenz Der MockCreator (Code in de.abstrakt.tools.codegeneration.*)
steht unter der GNU General Public License (GPL), die zu
importierenden Klassen im Package de.abstrakt.mock stehen
unter der GNU Lesser General Public License
(LGPL). Dadurch sind die generierten Klassen auch in
"closed source"-Projekten verwendbar. Und hier noch der Standardtext: Copyright (C) 2001/2002 abstrakt gmbh This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|||