もう少し柔軟な assertThat が欲しい

assertThat と hamcrest の組み合わせって便利ですよねー。
assertThat と hamcrest の組み合わせについては、
JDaveの寄り道にhamcrestを試してみる。 - Fight the Future
とか、
hamcrestのMatcherメモ - 都元ダイスケ IT-PRESS
とか見てもらえば大体分かると思う。


問題は、assertThat メソッド。

このメソッド、シグニチャ

public static <T> void assertThat(T actual, Matcher<T> matcher);

な感じになっている。
なので、

class Hoge { ... }
class ExHoge extends Hoge { ... }

Hoge hoge() { return new ExHoge(); }

なんてクラスとメソッドがあった場合に、

assertThat(hoge(), is(new ExHoge()));

なんてしてしまうと、コンパイルエラーになってしまう*1
こんな風にキャストすればいいんだけど、

assertThat(hoge(), is((Hoge) new ExHoge()));

激しください・・・


actual 側、つまり実際のコードでは抽象化されたものを使うけど、その assert にまで抽象化されたものを要求するのはちょっと微妙じゃないだろうか?
ってことで、こんなメソッドを作って、static import して使ってみた。

public static <T> void assertThat(T actual, final Matcher<? extends T> matcher) {
    org.junit.Assert.assertThat(actual, new BaseMatcher<T>() {
        @Override
        public boolean matches(Object obj) {
            return matcher.matches(obj);
        }
        @Override
        public void describeTo(Description description) {
            matcher.describeTo(description);
        }
    });
}

これで

assertThat(hoge(), is(new ExHoge()));

と書ける!
・・・んー、んー、なんかこんなこと書かなくても実現できそうな気もするんだけど・・・独自の Matcher 返す is メソッド書くとかなると、型パラメータが問題だし・・・
求む、もっといい感じの解決策!

*1:actual の型は Hoge、matcher の型 は Matcher となり、T が一致しない