2013-09-21 16 views
5

Mam prywatną metodę, która została wyśmiana w grails 1.3.7 za pomocą metaklasy, ale teraz, gdy uaktualniłem wersję Grails do 2.2.4, to samo kpina zawodzi.Jak wyśmiewać prywatne metody w kontrolerze w grails 2.2.4

Metoda testu wywołanie metody prywatnej

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

Mocking jest coś takiego

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

Odpowiedz

0

wierzę nie trzeba część .private.

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

powinny Wystarczająco dużo, ale powinienem określić typy parametrów jawnie

I, nawiasem mówiąc, należy zachować java nazewnictwa - metody nazwy powinny zacząć małymi charakteru

+1

Próbowałem, ale nie wydają się działać ... nic innego mi brakuje? – user1298426

0

Dla testów jednostkowych Użyłem Reflection metod prywatnych. Coś podobnego do tego powinno działać ...

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

najpierw dostać metodę z getDeclaredMethod ustawiania nazwy i typy parametrów można ustawić to dostepne i wreszcie tou nazwać z method.invoke przekazując obiekt, który ma metoda i parametry. Rezultatem jest obiekt, więc musisz go rzucić.

Wiem, że musi być lepszym rozwiązaniem, ale ten jest jedynym, odkryłem, że działa

Edycja: Niestety, co powyżej jest za wykonanie połączenia do prywatnej metody. myślę, że mam szydzili prywatną metodę, zanim po prostu robi ...

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

Tak jak napisałem, ale bez .private i znaku =. Ponadto, jak powiedział Kamil, powinieneś przestrzegać konwencji nazewnictwa dla nazw metod ...

+0

To wywoła prywatną metodę, która jest w mojej klasie kontrolerów, prawda? Chcę drwić z tej metody, zamiast ją nazywać. – user1298426

+0

To prawda, przepraszam, źle zrozumiałem pytanie ... – Eylen

1

Wygląda na to, że musisz zadeklarować typy argumentów zamknięcia (jego 100%, jeśli argumenty mają rzeczywisty typ, na przykład Long, ale nie pewnie o def, ale musisz spróbować):

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

... próbowałem, ale nie działałem. Próbowałem też \t \t def strict = mockFor (MyController) strictControl.demand.MyPrivateMeth1 {Użytkownik a, Konto b -> ... \t \t} – user1298426

6

Spróbuj użyć adnotacji @TestFor, która da ci zmienną kontrolera. Możesz następnie zmienić metaklas tego, a także włączyć sugestie Kamila Mikołajczyka i araxn1d. Więc całe badanie powinno chyba wyglądać następująco:

@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 
    } 
} 

Upewnij mieć def (lub String, Long, czy cokolwiek deklaracja użyć) na argumenty swojej makiety metody precyzyjnie, ponieważ są one na rzeczywistej prywatnej metody w kontrolerze, lub twój test spróbuje najpierw użyć normalnej prywatnej metody klasy.

Oto podobny test w Spocka:

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

Czy możesz podać sposób zwrócenia mapy z wyszydzanej metody kontrolera. robiąc to dostaję pewne wyjątki –

+0

W moim przykładzie powyżej, someOutput jest zmienną zwracaną przez wyśmiewaną metodę kontrolera. W moim przykładzie gdzie klauzula, ustawiłem go na ciąg znaków, ale równie dobrze można go ustawić na mapie. Zaktualizuję przykład. – jonnybot

Powiązane problemy