対向するWebサービスをどうしても利用しないとテストできないようなケースが発生する。
たとえば、Twitterアプリを作成している場合など。
Twitterのようなすでに動いているサービスが対向するwebサービスであれば、
テスト用のアカウントを作成しておいて、
そこにテスト用のTweetを入れておけばよいのではあるが、
しかしエンタープライズな場合だと、
そのような準備をできないこともある。
SIerの場合、後の工程(つまり総合試験)にそれらのテストを持って行って、
人月投入するというパターンがあるが、それはそれで、非常にまずい。
そんなわけで、手軽にWebサーバーを構築したいのだが、
tomcatにサーバーをまた立てて、モックのアプリサービスを書いて、
云々というのも非常に面倒臭い。
そこで登場するのがJettyという軽量Webサーバーです。
これはJUnitでもサーバーを立ち上げられる優れもので、テスト用にも利用出来るなかなか優れたういやつです。
ちなみに、現在はバージョン8まで登場しているそうですが、本稿で使用するのは
7.3.1
です。さて、早速コードをと言いたいところですが、
今回のサンプルは先に仕様の説明から。
- Webサーバーはlocalhostにポート3000で立てます。
- どのようなリクエストが来ても、レスポンスコード
200 : OK
を返します。 - コンテンツタイプは
"application/json"
を返します。 - メッセージ部分は
{"test_result" : "ok"}
というjsonが設定されます。
では、早速JUnitのテストコード
@BeforeClass
と@AfterClass
からどうぞ。
public class HttpGetResourceTest {
private static final String TEST_RESULT = "{\"test_result\" : \"ok\"}";
private static final int PORT_NUMBER = 3000;
private static final String LOCAL_HOST = "localhost";
private static Server server;
/**
* サーバーを起動する。
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
InetSocketAddress inet = new InetSocketAddress(LOCAL_HOST, PORT_NUMBER);
server = new Server(inet);
// 後述するHandlerの実装。
Handler handler = new RequestHandlerImpl();
server.setHandler(handler);
server.start();
}
/**
* サーバーを終了する。
*/
@AfterClass
public static void tearDownAfterClass() throws Exception {
server.stop();
server.destroy();
}
@BeforeClass
ではサーバーを起動して、@AfterClass
はサーバーをシャットダウンします。一応このテストクラスが実行されている間は、サーバーはローカルホスト3000番で起動します。
実際にどのような処理がなされるかは、このテストの内部クラス
RequestHandlerImpl
に記述します。では、
RequestHandlerImpl
をどうぞ。
private static class RequestHandlerImpl extends AbstractHandler {
@Override
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
Writer writer = response.getWriter();
writer.write(TEST_RESULT);
HttpConnection connection =
HttpConnection.getCurrentConnection();
Request req = connection.getRequest();
req.setHandled(true);
}
}
ここでは本当に先程の仕様通りに
- どのようなリクエストが来ても、レスポンスコード
200 : OK
を返します。 - コンテンツタイプは
"application/json"
を返します。 - メッセージ部分は
{"test_result" : "ok"}
というjsonが設定されます。
となっています。
あまり説明いらないですね。
では、サンプルのテストコードを書いてみましょう。
なお、このサンプルではApache HttpComponentsを利用しています。
@Test
public void testIsServerReady() throws Exception {
URI uri = URIUtils.createURI("http",
LOCAL_HOST, PORT_NUMBER,
"/search",
"user=mike_neck&start=10",
null);
HttpGet hGet = new HttpGet(uri);
HttpClient client = new DefaultHttpClient();
HttpResponse res = client.execute(hGet);
HttpEntity entity = res.getEntity();
if(entity != null){
StringBuilder builder = null;
InputStream input = null;
try {
input = entity.getContent();
InputStreamReader reader =
new InputStreamReader(input, "UTF-8");
builder = new StringBuilder();
while(reader.ready())
builder.append((char)reader.read());
}finally{
input.close();
}
assertThat("testIsServerReady",
builder.toString(),
is(TEST_RESULT));
}else{
fail();
}
}
適当なクエリーをつけてGetで呼び出しました。
ここの部分は実際のクラスを入れておく部分ですね。
と、まあこんな感じなわけですが、
多少依存性がありますので、その情報も書いておきます。
必要なライブラリーは
commons-logging.jar
jetty-continuation.jar
jetty-http.jar
jetty-io.jar
jetty-server.jar
jetty-util.jar
servlet-api.jar
です。
皆さん、Web連携アプリのテストもしっかりとやりましょう。
テスト部分で結果を取得する部分がうまく動かず、文字列が取得できませんでした。
返信削除Androidのテストで実行したからですかね?
BufferedReaderをつかったら、取得できたのでお知らせしておきますね。
----------
BufferedReader reader
= new BufferedReader(new InputStreamReader(input));
String line;
while( ( line = reader.readLine() ) != null )
{
Log.d("BumpRecorderTest", line);
builder.append(line);
}
こんばんは。
返信削除サーバーのテストができるのは、ありがたいですね。