2013-09-21 74 views
5

我有一個私有方法,在grails 1.3.7中使用元類來模擬,但現在我將grails版本升級到2.2.4,同樣的模擬失敗。如何在grails中控制控制器中的私有方法2.2.4

方法來測試具有私有方法的調用

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

嘲諷是這樣

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

回答

0

我相信你不需要.private.部分

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

應是足夠的,但我會明確指定參數類型

而且,順便說一句,你應該保持Java的命名約定 - 方法名稱應該以小寫字母

+1

我嘗試過,但似乎並沒有工作......別的我失蹤? – user1298426

0

開始單元測試我使用反射私人的方法。類似的事情這應該工作...

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

首先,你得到法getDeclaredMethod設置名稱和參數類型,將其設置入店最後土特產品與method.invoke稱呼它傳遞的是有對象方法和參數。結果是一個對象,所以你必須施放它。

我知道必須有一個更好的解決方案,但是這一次是唯一一個我發現,工作

編輯:對不起,什麼是上面是撥打電話到一個私有方法。 我認爲我只是在做之前嘲笑的私有方法...

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

就像你寫的,但沒有.private和等號(=)。另外,正如卡米爾所說,你應該遵循方法名稱的java命名約定......

+0

這將調用我的控制器類中的私有方法,不是嗎?我想嘲笑這種方法而不是調用它。 – user1298426

+0

這是真的,對不起,我誤解了這個問題... – Eylen

1

看來你需要聲明閉包參數的類型(如果參數有實際類型,那麼它是100%,例如Long,但不是確定關於def,但你需要嘗試):

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

雅...試過,但似乎沒有工作....我也試過\t \t def strict = mockFor(MyController) strictControl.demand.MyPrivateMeth1 {User a,帳戶b - > .... \t \t} – user1298426

6

嘗試使用@TestFor註釋,它會給你一個控制器變量。然後你可以改變它的元類,以及結合Kamil Mikolajczyk和araxn1d的建議。所以,你的整個測試也許應該是這樣的:

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

確保有高清(或字符串,龍,或任何聲明您使用)在您的模擬方法正是的參數,因爲它們是在控制器中的實際私有方法,或者您的測試將首先嚐試使用該類的普通私有方法。

下面是斯波克類似的試驗:

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

您能否請您提供從模擬控制器方法返回地圖的方式。在這樣做時我收到一些例外 –

+0

在我上面的例子中,someOutput是模擬控制器方法返回的變量。在我的示例where子句中,我將它設置爲一個字符串,但您可以輕鬆將其設置爲一個Map。我會更新這個例子。 – jonnybot