我有一個私有方法,在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 ->
...
}
我有一個私有方法,在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 ->
...
}
我相信你不需要.private.
部分
MyController.metaClass.MyPrivateMeth1 = { a, b -> ... }
應是足夠的,但我會明確指定參數類型
而且,順便說一句,你應該保持Java的命名約定 - 方法名稱應該以小寫字母
開始單元測試我使用反射私人的方法。類似的事情這應該工作...
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命名約定......
這將調用我的控制器類中的私有方法,不是嗎?我想嘲笑這種方法而不是調用它。 – user1298426
這是真的,對不起,我誤解了這個問題... – Eylen
看來你需要聲明閉包參數的類型(如果參數有實際類型,那麼它是100%,例如Long
,但不是確定關於def,但你需要嘗試):
MyController.metaClass.MyPrivateMeth1 = { def a, def b -> ... }
雅...試過,但似乎沒有工作....我也試過\t \t def strict = mockFor(MyController) strictControl.demand.MyPrivateMeth1 {User a,帳戶b - > .... \t \t} – user1298426
嘗試使用@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"
}
}
您能否請您提供從模擬控制器方法返回地圖的方式。在這樣做時我收到一些例外 –
在我上面的例子中,someOutput是模擬控制器方法返回的變量。在我的示例where子句中,我將它設置爲一個字符串,但您可以輕鬆將其設置爲一個Map。我會更新這個例子。 – jonnybot
我嘗試過,但似乎並沒有工作......別的我失蹤? – user1298426