JSFアプリケーションの単体テスト with Shale Test Framework (4)

Shale Test Framework(STF)を紹介しているエントリも,早くも3回目になってしまった。 前回のエントリでは,テストメソッドの説明の途中で強引に終わらせてしまった。今回はその続きを見ていこう。

まず,テストメソッドのソースコードを再び示しておこう。 前回のエントリでは,テスト対象のgetRightSelectItems()メソッドを呼び出すところまで解説した。

public void testGetRightSelectItemsValue1() throws Exception { externalContext.addRequestParameterMap(“fv”, “1”); target.getRightSelectItems(); assertEquals(“ContentType”, “text/javascript;charset=UTF-8”, response.getContentType()); JSONArray jsonArray = JSONArray.fromString(getContent()); assertEquals(“jsonArray.length”, 2, jsonArray.length()); assertSelectItem(jsonArray, 0, “宇都宮線”, “1”); assertSelectItem(jsonArray, 1, “高崎線”, “2”); }

今回のテスト対象のManagedBeanのメソッドでは,ResponseWriterオブジェクトに対して文字列をwriteしている。その検証のためには,テストメソッドからwriteされた文字列を取得する必要がある。

MockResponseWriter.jpg

AbstractJsfTestCaseクラスが提供するResponseWriterオブジェクトは,実際はMockResponseWriterクラスのインスタンスであり,これはMockRenderKitクラスが生成する。HttpServletResponseオブジェクトに関してもモッククラスが提供されていて,getWriter()メソッドで得られるWriterオブジェクトに関しても,MockPrintWriterクラスのインスタンスとなっている。MockPrintWriterオブジェクトは,CharArrayWriterオブジェクトに対して出力することが規定されているので,結果としてResponseWriterオブジェクトに対して出力された文字列は,CharArrayWriterオブジェクトの内部に蓄積され,MockPrintWriter#content()メソッドを使用して取り出すことができる。

話を元に戻そう。SelectItemsProducer#getRightSelectItems()メソッドでは,ResponseWriterオブジェクトに対して,コンテントタイプを”text/javascript;charset=UTF-8”というように指定している。これを4行目で検証している。AbstractJsfTestCaseクラスでは,実行時に存在するHttpServletResponseオブジェクトを,MockHttpServletResponseクラスのインスタンスとして,responseインスタンスフィールドにセットしてくれている。responseフィールドのgetContentType()メソッドの戻り値について,正しくコンテントタイプがセットされたかどうかを検証できる。

さて,いよいよ出力されたJSON形式のテキストの検証だが,テキストのまま検証するのはかなり難しく,手間である。幸いにも,JSON形式のテキストをパースしてオブジェクトとして扱うことを可能にするライブラリが,今日ではいくつか提供されている。今回は, json-libというライブラリを使ってみよう。

json-lib.jpg

と,その前に,SelectItemsProducer#getRightSelectItems()メソッドが出力した文字列を取得しなければならない。その処理を,getContent()メソッドにまとめてみた。

private String getContent() throws IOException { MockPrintWriter writer = (MockPrintWriter)response.getWriter(); char[] cs = writer.content(); return String.valueOf(cs); }

responseフィールドのgetWriter()メソッドの戻り値をMockPrintWriterクラスでダウンキャストする。そして,content()メソッドを呼び出して,出力された文字列を文字配列として取得,その後1つの文字列として返却している。

ここで,SelectItemsProducer#getRightSelectItems()メソッドが出力するテキストがどういうものかを把握しておこう。

getRightSelectItems-result.jpg

大括弧で括られていることから,配列形式であることがわかる。その中に,”label”や”value”という要素が含まれている。json-libでは,配列をJSONArrayクラスで,個々の要素をJSONObjectクラスで,それぞれ扱うことが出来る。

まずは,getContent()メソッドで得られた文字列全体を,JSONArrayオブジェクトにパースする。それが5行目である。JSONArray#fromString()メソッドを使って,JSONArrayオブジェクトに変換する。仮に,出力結果がJSON形式として不正なものだった場合は,パースに失敗し,JSONException例外が発生する。このパース作業によって,出力結果がJSON形式として妥当かどうかを検証できる。

パースした結果のJSONArrayオブジェクトには,各要素をJSONObjectオブジェクトとして保持しているはずである。まずは,その件数を検証する。6行目において,JSONArray#length()メソッドを呼び出すことで要素の個数を取得し,宇都宮線と高崎線の2個かどうか検証している。

次に,各要素の検証だが,これはassertSelectItem()メソッドにまとめてみた。

private void assertSelectItem(JSONArray jsonArray, int index, String label, String value) { JSONObject jsonObj = jsonArray.getJSONObject(index); assertEquals(“jsonArray[” + index + “].label”, label, jsonObj.getString(“label”)); assertEquals(“jsonArray[” + index + “].value”, value, jsonObj.getString(“value”)); }

JSONArrayオブジェクトのgetJSONObject()メソッドにインデックスを渡すことによって,各要素をJSONObjectクラスのインスタンスとして取得することができる。さらに,JSONObject#getString()メソッドに名前を渡すことで,それに対する値を得ることができる。ここで検証したい値は,”label”と”value”の値。引数に正しい値を指定して,それぞれが一致するかどうかを検証している。

STFを使用することによって,JSFの実行時の環境をシミュレートした上で,テストメソッドを記述することができる。特に,Shale Remotingを使ったManagedBeanや,JSFコンポーネントを自作した場合について,STFは手放せないライブラリとなるはずだ。

Shale Remotingと合わせて,是非試してみて欲しい。

このエントリーをはてなブックマークに追加

関連記事

2023年のRemap

Remapにファームウェアビルド機能を追加しました

Google I/O 2023でのウェブ関連のトピック

2022年を振り返って

現在のRemapと今後のRemapについて