最近ようやくテストコードを書くことに目覚め始めました。
で、まぁ、とあるクラスをテストしようと思ったが、一部にミドルウェアと通信する箇所があるので、そこはユニットテストのときはなんもしないようにしたかった。DI なんて便利なモノがまだ無い環境なので、インスタンス生成のメソッドを protected にして、ユニットテストするときはモッククラスを返す、というやり方を試みた。
コード的にはこんな感じ。
//テストしたいクラス public class Hoge { public void hogeMethod() { //いろいろなコード MiddlewarePiyo piyo = createMiddlewarePiyo(); middleware.piyoMethod();//ミドルウェアとごにょごにょする //いろいろなコード } protected MiddlewarePiyo createMiddlewarePiyo() { return MiddlewarePiyo.getInstance(); } } public class HogeTest { @Test public void testHogeMethod() { Hoge h = new HogeMock(); h.hogeMethod(); assert(... } private class HogeMock extends Hoge { @Override public MiddlewarePiyo createMiddlewarePiyo() { return new MiddlewarePiyo() { @Override public void piyoMethod() {//ユニットテスト時は何もしなくする } } } } }
と、ここまで書いて HogeMock がコンパイルエラー。The constructor xxxx() is not visible. って、えー? まじっす? と思って Piyo クラスのコンストラクタをチェックしてみると……
public class MiddlewarePiyo { private MiddlewarePiyo() {}
コンストラクタが private 指定されていた……そりゃ not visible ですわな。ユニットテストのためにスコープを protected に変えたいのだけど、ソースは見れてもいじる権限が無いのでいかんともしがたい。そういえば WEwLC 本でも Singleton まわりは色々書いてあったよなぁーと思いつつ、一応 static factory method も見てみる。
public class MiddlewarePiyo { private MiddlewarePiyo() {} public static MiddlewarePiyo getInstance() { return new MiddlewarePiyo(); } }
Singleton ですらなかった。単に static factory method でコンストラクタに名前持たせたかっただけっぽいなー。
あきらめきれずに色々ぐぐったが、基本的にはコンストラクタのスコープゆるめればいいっしょ、というコメントがほとんど。Testing a class with private constructor をみると JUnit-addons なるものがあり PrivateAccessor を使えばいけるんじゃね? 的なことが書いてあるが……こいつは 3.7 and JUnit 3.8.x 対応までで止まってるっぽい。
うーん、だめかー……