バイトのtestで、Spockでさらっとtest書いて、
いざ全pattern cross check! と思ったら、
無限loopになるpatternが多くて。
@Timeout導入でサクッと、と思ったら、
loop回るのが早くて凄いmemoryと時間を食って、
@Timeoutでは抑えきれません。
うーむ、それじゃぁGroovyのmetaClassでmethodの振る舞いを変更だ!
と思ったら、どうやっても振る舞いが変わりません。
悩んだ末、GroovyのmetaClassでの再定義は、
外側のJava classには及ばない(Groovyの世界の中だけ)、と結論。
仕方無いじゃぁJMockitだ!
って思ったんですが、今度はSpockとJMockitは相容れないようで、
Caused by: java.lang.UnsupportedOperationException: Attempted to redefine class loaded from custom class loader
なのでJAVA_OPTS=-javaagent:.../jmockit-1.37.jarをつけて実行すると今度は、
mockit.internal.ClassFile$NotFoundException: Unable to find class file for Test2$1
spockは諦めました。
ならばせめてJUnit5だ! と思ったんですが、build.gradleで、
junitAnt 'org.apache.ant:ant-junit4:1.10.1'
と指定しているので、敢え無く撃沈。
調べるとどうも、JUnit5とAntを組み合わせる動きはないんですよね。
それでも Ant を使いたい人のための JUnit 5というのもありましたけど、これは、
<java fork="true" classname="org.junit.platform.console.ConsoleLauncher">
で無理矢理実行してるだけですから、ちょっと違います。
こちとら、build.gradleからant.junitAnt(...)で呼んでいるので、
ConsoleLauncherだと困るんです(→どうやって書いたらいいかよくわからない)。
結局、JUnit4 + JMockit で書きました。
TimeoutやExpectedExceptionは@Ruleにしてちょこっと今っぽくしましたけど、
そのくらいが関の山でした。
ant.junitAnt(...)でfork:trueにして、また更に
junit4.jarよりjmockit.jarを先に書いておかないと
IllegalStateExceptionが出る(gradle + jmockitでjava.lang.IllegalStateExceptionって出たので対応)、
というのでそう書いたしgradle --stacktraceしてload順確認したんですけど、
それでもException出たので、
jvmarg(line:"-javaagent:${configurations.jmockit.asPath.split(':')[0]}")
を入れて漸く動きました。
けど、折角JMockit入れたのに、
やっぱり別の時にはTimeoutも必要で。
JUnit4だと@RuleつけてTimeout.millis(200)でいいんですね今。
そしたら、JMockitで振る舞い変えなくても、
GroovyでなくJavaならTimeoutだけで済むじゃーないですかー!
うぁーん。
あとはParameterized Testにしました。
JUnitParamsが簡便そうです。
何がいいって、JUnit4標準の方法だとinstance fieldがparameterになるので、
全methodについて回っちゃいませんか? というのが不安で。
JUnitParamsなら、明示的に単一methodに対してparameter指定できるので安心です。
…ダメです。JUnitParams使うと、Timeout効かないことがわかりました。
悲しい。