Groovy/Maven/Java + TestNG Example ではGroovyを使うことでJavaのprivateフィールドを簡単に参照・更新出来ることを紹介しました。
そこで、より実用的なシーンとしてxUnit等による単体テストの作成でしばしばぶつかる、JavaのSingletonデザインパターンのmock/stub化をGroovyで攻略してみます。
サンプルコードは以下のGistにUPしています。
以下のようなディレクトリ構成になります。
gjt3/ pom.xml src/ main/java/gjt3/Singleton.java test/groovy/gjt3/SingletonTest.groovy
Singleton.javaはSingletonの手抜き実装です。privateなコンストラクタにgetInstance()経由で文字列を渡して、インスタンスを区別出来るようにしてます。
Groovy + TestNGで組み立てたテストコードの内容を紹介します。
// 最初の2つは、通常のSingletonの動作確認です。 Singleton s1 = Singleton.getInstance("s1"); Assert.assertEquals(s1.getArg(), "s1"); // getInstance()したのは、上で初期化した"s1"を返すはずです。 Singleton s2 = Singleton.getInstance("s2"); Assert.assertEquals(s2.getArg(), "s1"); // Groovyでprivateなコンストラクタを呼び出しインスタンス化します。 Singleton s3 = new Singleton("s3"); Assert.assertEquals(s3.getArg(), "s3"); // これを、privateなSingletonインスタンス保管用のフィールドにセットします。 Singleton.instance = s3; // getInstance()してみると、上で上書きした"s3"のインスタンスが返されます。 Singleton s4 = Singleton.getInstance("s4"); Assert.assertEquals(s4.getArg(), "s3");
当然ですがテストはpassします。
ただし注意点として、SingletonはClassのフィールドにセットされますので、テストコード中でこれを弄った後は、必ず元のインスタンスに戻しておく必要があります。テストコード中でmock用のインスタンスに差し替え、そのままにしてしまうと、後に続くテストコードが失敗する可能性があります。