JAX-RSのユニットテストまわり
JAX-RSのClient APIを確認した流れで、ユニットテストまわりも眺めてみる。
- Jersey - 2.17
- RESTEasy - 3.0.9.Final
各実装のテストサポート
軽くコード書いてみたりしつつ思ったことをば。
Jerseyさん
Jerseyさんのテスティングフレームワークを使うには、jersey-test-framework-core
と、テストで使うコンテナのproviderが要ります。providerはいくつか用意されているので、好きなのを依存に追加しましょう。
testCompile "org.glassfish.jersey.test-framework:jersey-test-framework-core:${jerseyVersion}" // grizzly2, inmemory, jdk-http, simple, jetty... testCompile "org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:${jerseyVersion}"
providerは自分で作ることもできるし、複数を使い分けることもできます。使い分ける需要がどれほどあるかはわからないけど。 テストでカバーできる範囲をproviderの選択で切り替えれる感じかな。何を選択するかはどんなテストをしたいかとかにもよるけれど、実行速度の差は結構あるので一つの判断材料になるかもしれない。(jdk-httpだと20ケースで40秒程度かかる。inmemoryだと20ケース2秒程度で、500ケースだと17秒。grizzlyもたいがい早い。数増えると結構変わりますね。)
JerseyTestを使用したテストコードはこんな感じ。
public class HogeTest extends JerseyTest { @Test public void test() throws Exception { String response = target("hoge") .request() .get(String.class); assertThat(response, containsString("HOGE")); } @Override protected Application configure() { return new ResourceConfig(Hoge.class); } }
ポイントは前に紹介したJAX-RSのClientAPIがそのまま使用されている点。なのでコード内に登場するテストに特化した知識はこれくらいです。
- テストクラスで
JerseyTest
を継承すること。 configure
メソッドをオーバーライドすること。
JerseyTest
をJUnitのRule
にしてもいいとは思いますが、Jerseyのテストに特化するなら継承枠を使っていいと思います。Rule
あったらそっち使うけどね。
RESTEasy
こちらのアプローチはMockを使う形です。そしてこのMockさんたちはresteasy-jaxrsに直接入っているため、別に依存ライブラリを追加する必要はありません。コンテナ使うのはArquillianをーって住み分けなんだろうか。
@Test public void test() throws Exception { Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); dispatcher.getRegistry() .addResourceFactory(new POJOResourceFactory(Hoge.class)); MockHttpResponse response = new MockHttpResponse(); dispatcher.invoke( MockHttpRequest.get("hoge"), response); assertThat(response.getContentAsString(), containsString("HOGE")); }
継承などを使用しない分、Dispatcher
まわりはゴテゴテする感じだけれど、プロダクトで採用するならこの辺はRule
にするだろうから問題ない。Dispatcher
にRequest
とResponse
を渡してResponse
を検証する形は独特だけれど、それほど違和感もないと思います。
これを記憶を頼りに書くのは少々厳しく感じますので、使うときはドキュメントを眺めるとしましょうか。
こちらのすぐに挙げられる利点は500ケースでも5秒程度と言う結構な早さ。
まとめのような雑感
JAX-RSはPOJOで書けるのが強みなので、JAX-RSのクラスに書かれたロジックをテストしたいなら素のJUnitのテストとして書くのがいいです。それなら500ケースでも0.1秒とかそんなのですしね。
ここで挙げた子たちは、JAX-RSならではの機能のテストに限定するべきでしょう。たとえば@Path
に書いたのが期待通りになっているかとか、ProviderやFilterが期待通り動いてるかとか。
なんでもかんでもフル環境でやってるとフィードバックが遅くなるので、なるべく小さく確認できる方法を知っておくと色々捗ります。それぞれの道具を使うことで、何を検証できるか(そして何ができないか)を把握しておくと良いです。
APIデザインの極意に「テストをサポートしないのは開発者をがっかりさせる簡単な方法だ(やや曲解)」って書いてたりするけれど、だいたいのよく知られたフレームワークはテストをサポートしています。ここで挙げた子たちともうまくやっていきたいなと思いました。まる。
APIデザインの極意 Java/NetBeansアーキテクト探究ノート
- 作者: Jaroslav Tulach,柴田芳樹
- 出版社/メーカー: インプレスジャパン
- 発売日: 2014/05/23
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (6件) を見る
メモ: gradleとか使わずにJerseyTestを使おうとしたならば
jar4個突っ込めば動きそうな気配はある。 →Gistに投げ込んだのを参照
でもたまに書いてるけど、手作業で依存をごにょごにょする時代は終わってますやね。