2013-09-21 9 views
5

Ich habe eine private Methode, die in Grails 1.3.7 mit Metaklasse verspottet wurde, aber jetzt, dass ich Grails Version auf 2.2.4 aktualisiert, das gleiche Spott fehlschlägt.Wie private Methoden in Controller in Grellen 2.2.4

Methode zum Test hat einen Aufruf an private Methode

private def MyPrivateMeth1(def arg1, def arg2) { 
... 
} 

Mocking ist so etwas wie dieses

MyController.metaClass.private.MyPrivateMeth1 = { a, b -> 
... 
} 

Antwort

0

ich Sie nicht glauben, müssen die .private. Teil

MyController.metaClass.MyPrivateMeth1 = { a, b -> ... } 

sollte genug, aber ich würde explizit Parametertypen

angeben

Und, nebenbei bemerkt, sollten Sie Java-Namenskonventionen halten - Methoden Namen mit Kleinbuchstaben

+1

ich es versucht, aber scheint nicht zu funktionieren ... alles, was ich bin fehlt? – user1298426

0

Für Unit-Tests beginnen sollte ich Reflexion für private Methoden verwendet haben. Etwas ähnliches wie dies funktionieren sollte ...

Method method = BehaviourService.getDeclaredMethod("behaviourValidConstraints",User.class,Behaviour.class) 
method.setAccessible(true) 
boolean valid = ((Boolean)method.invoke(service, user,b)).booleanValue() 

Zuerst erhalten Sie die Methode mit getDeclaredMethod den Namen und die Parametertypen einstellen, setzen Sie es zugänglich und schließlich mit method.invoke tou rufen Sie das Objekt übergeben, die das hat Methode und die Parameter. Das Ergebnis ist ein Objekt, also musst du es umwandeln.

Ich weiß, es muss eine bessere Lösung sein, aber dies ist die einzige, die ich gefunden habe, die

bearbeiten arbeitet: für einen Anruf an eine private Methode Sorry, was oben ist, ist. Ich denke, dass ich verspottet habe, schrieb man es wie eine private Methode vor nur tun ...

MyController.metaClass.myPrivateMeth1 { a, b -> 
... 
} 

Gerade aber ohne die .private und dem = -Zeichen. Auch, wie Kamil sagte, sollten Sie Java-Namenskonventionen für Methodennamen ...

+0

Das wird die private Methode aufrufen, die in meiner Controller-Klasse ist, oder? Ich möchte diese Methode verspotten, anstatt sie zu nennen. – user1298426

+0

Es ist wahr, sorry, ich missverstanden die Frage ... – Eylen

1

Es scheint, folgen, dass Sie Verschlussart Argumente (sein 100% erklären müssen, wenn die Argumente tatsächliche Typen, zum Beispiel Long, aber nicht sicher über def, aber Sie müssen es versuchen):

MyController.metaClass.MyPrivateMeth1 = { def a, def b -> ... } 
+0

ya ... versucht, aber schien nicht zu arbeiten .... Ich versuchte auch \t \t def strict = mockFor (MyController) strictControl.demand.MyPrivateMeth1 {Benutzer a, Konto b -> .... \t \t} – user1298426

6

Verwenden Sie die @ TestFor Annotation, die Ihnen eine Controller-Variable geben wird. Sie können dann die Metaklasse ändern, sowie die Vorschläge von Kamil Mikolajczyk und araxn1d einbeziehen. Also, sollten Sie Ihre ganze Test wahrscheinlich so aussehen:

@TestFor(MyController) 
class MyControllerTests { 

    setup() { 
     controller.metaClass.MyPrivateMeth1 = {def arg1, def arg2 -> 
      //you can make your mocked method return whatever you wish here 
      return [key1: "foo", key2: "bar"] 
     } 
    } 
    void testForSomething() { 
     //Some code here that invokes an action or two in your controller which in turn invokes the private method 
    } 
} 

Stellen Sie sicher, def zu haben (oder String, Lange, oder was auch immer Erklärung Sie verwenden) auf die Argumente des Mock Methode genau, wie sie auf die sind tatsächliche private Methode im Controller, oder Ihr Test wird versuchen, zuerst die normale private Methode der Klasse zu verwenden.

Hier ist ein ähnlicher Test in Spock:

import spock.lang.Specification 
import spock.lang.Unroll 
import grails.test.mixin.* 
import org.junit.* 
@TestFor(MyController) 
class MyControllerSpec { 

    def "test that thing"() { 
     setup: 
      controller.metaClass.MyPrivateMeth1 = {def arg1, def arg2 -> return someOutput } 
     expect: 
      controller.someAction() == expectedRender 
     where: 
      someOutput        | expectedRender 
      [key1: "foo", key2: "bar"]    | "expected render from controller" 
    } 
} 
+0

Können Sie bitte die Möglichkeit geben, eine Karte von der verspotteten Controller-Methode zurückzugeben. dabei bekomme ich einige Ausnahmen –

+0

In meinem Beispiel oben ist SomeOutput die Variable, die von der Mocked-Controller-Methode zurückgegeben wird. In meinem Beispiel where-Klausel habe ich es auf eine Zeichenfolge festgelegt, aber Sie könnten es genauso gut auf eine Map setzen. Ich werde das Beispiel aktualisieren. – jonnybot

Verwandte Themen