tokuhirom's Blog

[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 遅いと思うかもしれないですが、意外と起動はやいです。

出来てみると簡単ですが、意外とこういうことしてるコード見当たらなかったんで、書いてみた次第。

もっといいテスト方法あるよ! なんて方いたら教えてくだされ~