| 

.NET C# Java Javascript Exception

Methoden ersetzen

Dies ist das Archiv des ehemaligen Forums zum Thema Groovy, Grails, Griffon und Bean Scripting Framework, welches unter groovy-forum.de existierte. Die neue Adresse des Groovy-Forums ist: http://codekicker.de/fragen/themen/groovy.


Methoden ersetzen

phabi - 05.10.2010 13:02
hallo zusammen

ich bin neu in der groovy-szene und verzweifle mit einer scheinbar sehr einfachen aufgabe. ich möchte in einem groovy unit-test auf einer bestimmten klasse die methode ersetzen und zwar global, egal, wo instanzen erzeugt werden (auch wenn sie von java-objekten erzeugt werden).

mein test sieht wie folgt aus:

@Test
public void testQuitApplication() {
ApplicationContext.metaClass.isProgressOngoing = {-> return true }
ApplicationContext ctx = new ApplicationContext()
// this line prints "true"!
System.out.println(ctx.isProgressOngoing()?"true":"false")
MyAppMain main = new MyAppMain()
main.startUI = false
def retval = main.osxQuitHandler()
assert retval == false
}

die methode osxQuitHandler braucht die overridden methode isProgressOngoing() auf dem von ihr erzeugten kontext. diese methode soll true zurückliefern, macht sie aber nicht. nur die im test angelegte instanz des ApplicationContext tut dies korrekt. scheinbar hab ich hier ein konzept von groovy noch nicht verstanden. kann da jemand auf die sprünge helfen?


Re: Methoden ersetzen

Wicki - 05.10.2010 14:27
Hallo,

ich bin auch nicht gerade ein groovy-Profi, aber das Code-Stückchen was Du hier anbietest, ist für meinen Geschmack etwas wenig. Meistens wird man hier im Forum etwas ausprobieren, testen wollen, um evtl. eine Lösung anbieten zu können.
Was verbirgt sich hinter
Zitat

Test, ApplicationContext, MyAppMain
?
Auch mit dem Satz
Zitat

die methode osxQuitHandler braucht die overridden methode isProgressOngoing()
auf dem von ihr erzeugten kontext
kann ich nicht viel anfangen.
Vielleicht versuchst Du es nochmal ein bischen ausführlicher.

Gruß Wicki


Re: Methoden ersetzen

phabi - 05.10.2010 15:52
hallo wicki

danke für deine antwort. der inhalt dieser klassen ist eigentlich völlig unwichtig. die klassen sind viel zu gross und würden hier nur verwirren. ich versuchs daher mal allgemein zu formulieren:


---- java classes -----
public class Context {
public boolean isProgressOngoing() {
return false;
}
}

public class MyAppMain {

private Context context = new Context();

public boolean osxQuitHandler() {
return !context.isProgressOngoing();
}
}

----- groovy test ----

@Test
public void testQuitApplication() {
// methode isProgressOngoing soll immer true zurückliefern
Context.metaClass.isProgressOngoing = {-> return true }
MyAppMain main = new MyAppMain()
def retval = main.osxQuitHandler();
// hier erwarte ich false, erhalte aber immer true
assert retval == false;
}


gruss
fabi


Re: Methoden ersetzen

Wicki - 05.10.2010 17:23
Hallo fabi,

ich hab mal Deinen Code lauffähig gemacht und teilweise ergänzt. Welche Rolle die Annotation "Test" spielt ist mir allerdings unbekannt. Also davon abgesehen ist bei mir die Assertion richtig. Die Closure liefert "true" und der "osxQuitHandler" macht daraus "false".
public class Context {
  private int w=0; //beliebiger Wert
  public Context(int w) {
  	this.w = w;
  }
  public boolean isProgressOngoing() {
  	println "In isProgressOngoing..."
    return false;
  }
}

public class MyAppMain {

  private Context context = new Context(16);
  
  public boolean osxQuitHandler() {
  	boolean rc=!context.isProgressOngoing()
  	println "RC in osxQuitHandler:$rc"
    return rc;
  }
}

//----- groovy test ----

//@Test
public void testQuitApplication() {
  // isProgressOngoing wird die Closure zugewiesen
  // methode isProgressOngoing soll immer true zurückliefern
  Context.metaClass.isProgressOngoing = {-> println "w="+w;return true }
  MyAppMain main = new MyAppMain()
  def retval = main.osxQuitHandler();
  // hier erwarte ich false, erhalte aber immer true
  assert retval == false;
}
testQuitApplication()

Gruß Wicki


Re: Methoden ersetzen

phabi - 05.10.2010 17:50
hmm... bei mir läuft immer noch nichts. :( du hast aus den java-klassen groovy-klassen gemacht. vielleicht funktioniert's deshalb bei dir. (der grund, weshalb ich die @Test anweisung brauch, ist weil's sich hierbei um einen junit-test handelt.) oder funktioniert's auch, wenn du die beiden java-klassen als .java - files erstellst?


Re: Methoden ersetzen

Wicki - 08.10.2010 09:13
Hallo phabi,

melde mich etwas verspätet zurück. Du hast recht, mit den Java-Klassen klappt das nicht so ohne weiteres. Ich habe dazu folgenden Vorschlag:
//************ Java-Klasse Context.java
//****** Compile:
//****** javac -cp.;%GROOVY_HOME%\embeddable\groovy-all-1.7.3.jar Context.java  //ggf. anpassen !
//Der Klasse werden Groovy-Eigenschaften zugeordnet
public class Context extends groovy.lang.GroovyObjectSupport {
  private int w=0; //beliebiger Wert, bedeutungslos, nur zur Kontrolle
  public Context(int w) {
  	this.w = w;
  	System.out.println("Context:"+w);
  }
  public boolean isProgressOngoing(boolean var) {
  	boolean rc;
  	if (var) {  //hier wird die originale Methode abgearbeitet
  	  System.out.println("In isProgressOngoing...");
  	  rc = true;
  	} else {    //Aufruf der Closure-Methode, Return-Code ist boolean
  	  Object ob=getMetaClass().invokeMethod(this,"clsMethod",null);
  	  rc = ((Boolean)ob).booleanValue();
  	  System.out.println("Nach clsMethod...:"+rc);
        }
        return rc;
  }
}

//************ Java-Klasse MyAppMain.java
//****** Compile: javac -cp.;%GROOVY_HOME%\embeddable\groovy-all-1.7.3.jar MyAppMain.java
public class MyAppMain {
  private Context context = new Context(16);
  public boolean osxQuitHandler(boolean var) {
     boolean rc;
     rc=!context.isProgressOngoing(var);   //Variante 'var':isProgressOngoing oder clsMethod
     System.out.println("RC in osxQuitHandler:"+rc);
     return rc;
  }
}

//************ Groovy-Skript Test1.groovy
//****** Aufruf: groovy Test1
//@Test
public void testQuitApplication() {
  println "--------------"
//  def originalMethod = Context.metaClass.getMetaMethod("isProgressOngoing")//, method_arguments)
  //zur Klasse 'Context' wird eine neue Methode (Closure) hinzugefügt
  Context.metaClass.clsMethod = { args ->
  //überlagern der Original-Methode funktioniert nicht
//	Context.metaClass.isProgressOngoing = { args ->
	// tue irgendetwas ...
	println "In clsMethod..."
	def result = false
	//Möglichkeit die Originalmethode aufzurufen
//	  def result = originalMethod.invoke(delegate,args)
//	  println "Result:$result"
        return result
  }
  MyAppMain main = new MyAppMain()
  def retval = main.osxQuitHandler(true); //true/false: Original-/Closure-Methode
  println "retval:$retval"
}
testQuitApplication()

Vielleicht hilfts Dir ?

Gruß Wicki


Re: Methoden ersetzen

phabi - 08.10.2010 10:06
hallo wicki! cool, dein hint hat mich auf eine idee gebracht, mit der ich schlussendlich das problem lösen konnte! super, vielen dank für deine hilfe! :o)


Stelle deine Groovy-Frage jetzt!


Diese Seite zeigt den Thread "Methoden ersetzen" der ehemaligen Webseite groovy-forum.de, welche durch einen Serverunfall zerstört wurde. codekicker.de hat viele Konversationen über die beliebte Programmiersprache Groovy und zugehörige Frameworks wie das Grails-Framework retten können.

Hast Du eine Frage zum Thema Groovy, Grails oder allgemein Java? Viele ehemalige groovy-forum.de Mitglieder beantworten dir auf codekicker.de deine Frage! Stelle jetzt eine Frage!

Viele weitere Diskussionen zu Grails und Groovy befinden sich auf der Threadübersicht des alten groovy-forum.de.