テストコードを Groovy と Spock で生産性よく書いていますが、
プロダクトコードは政治的な都合により Java で書いています。
プロダクトコードが Java、テストコードが Groovy だと大体の場合は
Groovy や Spock のお作法で問題なくテストコードをかけますが、
static メソッドだけはうまくいきません。
前提事項の整理
Groovy には metaClass という便利なものがありますが、
Java で実装されたクラスに対しては metaClass を使ってふるまいを変更できません。
また、Spock の Mock は static メソッドには使えません。
一方で、実際の開発ではユーティリティという名の static メソッドが
あふれかえっているため、テストコードを書こうとすると結構苦労します。
(static メソッドの中で DB アクセスとか平気で実行されて…むむむ)
jMockit を使えば…?
Groovy の公式サイトには Java クラスの static メソッドに対しては
jMockit 使えばモック化できるみたいなことを書いています。
http://groovy.codehaus.org/Mocking+Static+Methods+using+Groovy
http://groovy.codehaus.org/Using+JMockit+with+Groovy
mockit.Mockit クラスの redefineMethods メソッドを使うサンプルが紹介されています。
が・・・ Mockit クラスには redefineMethods メソッドが存在しません。
ver 0.999 と ver 1.8 で見てみましたが存在しませんでした。ver 1.8 は Mockit クラス自体いない状態です。
mockit.MockUp クラスを使うと、うまくいきました
サンプルコード①:static メソッドのある、モック化対象クラス
package sample;
public class JavaSampleClass {
public static String staticMethod1(String value1, int value2) {
return value1 + staticMethod2(value2);
}
public static int staticMethod2(int value3) {
return value3 * 2;
}
}
サンプルコード②:Spock テストコードで MockUp クラスを使う
package sample
import mockit.Mock
import mockit.MockUp
import spock.lang.Specification
class SpockSampleSpec extends Specification {
def "staticMethod1は「第1引数の文字列」と「staticMethod2メソッドに第2引数を渡した結果」を結合した文字列を返す"() {
given:
new MockUp<JavaSampleClass>() {
@Mock
int staticMethod2(int value3) {
return value3
}
}
expect:
JavaSampleClass.staticMethod1("abc", 1) == "abc1"
}
}
補足
jMockit モック化するメソッドの期待値を実装する Expectations や NonStrictExpectations を
Spock で使おうとすると実行時エラーになります。
new Expectations() {{
JavaSampleClass.staticMethod1("abc", 1); result = "abc1";
}};