[java] web.xml から tomcat-embed をランダムポートで起動し、起動したポートを得る方法、または Java webapp のテスト手法について
一般的に web application のテストをするには application server を別スレッドで起動してそこにアクセスする方法と、http request を mocking して application code を直接呼ぶ方法があります。前者の方法は、app server の挙動を完全に再現できるし、http client も使い慣れたものを利用できるというメリットがあります。後者の場合には実行速度が速いというメリットがあります。
で、いろいろなメリット・デメリットを考慮した結果、今回は前者の方法でいこうとおもったわけです。
ここでは、maven 構成な一般的な webapp を tomcat で運用する場合のテストを前提とします。
とりあえず、pom.xml に以下のように記述しましょう。tomcat は 7 を使う無難さよ。
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>7.0.56</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>7.0.56</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>7.0.56</version>
<scope>test</scope>
</dependency>
以下のように、tomcat-embed を起動すればいいだけです。めっちゃ簡単ですね。
Tomcat tomcat = new Tomcat();
tomcat.setPort(0);
org.apache.catalina.Context webContext = tomcat.addWebapp("/", new File("src/main/webapp").getAbsolutePath());
webContext.getServletContext().setAttribute(Globals.ALT_DD_ATTR, "src/main/webapp/WEB-INF/web.xml");
webContext.setJarScanner(new JarScanner() {
@Override
public void scan(JarScanType scanType, ServletContext context,
JarScannerCallback callback) {
// do nothing.
}
@Override
public JarScanFilter getJarScanFilter() {
return null;
}
@Override
public void setJarScanFilter(final JarScanFilter jarScanFilter) {
// do nothing.
}
});
tomcat.start();
int port = tomcat.getConnector().getLocalPort();
String url = "http://127.0.0.1:" + port;
// url をつかってなにか処理する
めっちゃ簡単ですね!! Embedded tomcat 遅いと思うかもしれないですが、意外と起動はやいです。
出来てみると簡単ですが、意外とこういうことしてるコード見当たらなかったんで、書いてみた次第。
もっといいテスト方法あるよ! なんて方いたら教えてくだされ~