JAX-RS+CDIをArquillianでテスト
公式ドキュメント: http://arquillian.org/guides/getting_started_ja/
参考: Arquillianでインテグレーションテスト最初の第一歩
タイトル通り、JAX-RS+CDIなのをArquillianでテストしてみようっていうネタ
構成
├── build.gradle └── src ├── main │ ├── java │ │ └── sample │ │ ├── Greeter.java │ │ ├── Hoge.java │ │ ├── SampleController.java │ │ └── SampleApplication.java │ └── webapp │ └── WEB-INF │ ├── beans.xml │ └── web.xml └── test ├── java │ └── sample │ └── SampleTest.java └── resources └── arquillian.xml
てな感じで。まずアプリケーション側を先に
SampleApplication.java
package sample;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
@ApplicationPath("resources")
public class SampleApplication extends ResourceConfig {
public SampleApplication() {
packages("sample");
}
}
Hoge.java
package sample;
public class Hoge implements Greeter {
@Override
public String greet() {
return "hoge";
}
}
※Greeterはただのインターフェースなので省略する
SampleController.java
package sample;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("/sample")
public class SampleController {
@Inject
Greeter greeter;
@Path("/greet")
@GET
public String greet() {
return greeter.greet();
}
}
src/main/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>
JAX-RS準拠なglassfishを使うので特に設定する必要なく、SampleApplicationで@ApplicationPathで設定しているので、/resources/sample/greetでアクションを実行出来るっていう感じで
src/main/WEB-INF/beans.xml
<?xml version="1.0" ?>
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1"
bean-discovery-mode="all">
</beans>
これがないと@Injectによる依存性の注入が上手く作用しないはずなので
これでアプリケーション側はオッケー。まぁ試しにglassfishとかにデプロイしてみりゃ実行出来るかと思うので
でこれをarquillianを使ってテストする
build.gradle
apply plugin: "java"
apply plugin: "war"
apply plugin: "eclipse"
repositories {
mavenCentral()
}
dependencies {
compile "javax:javaee-api:7.0"
testCompile "junit:junit:+"
testCompile "org.hamcrest:hamcrest-all:+"
testCompile "org.jboss.arquillian.junit:arquillian-junit-container:+"
providedCompile "org.glassfish.jersey.containers:jersey-container-servlet:2.+"
// arquillianでテストする際のContainer Adapterが必要になる。今回はglassfishを使ってるのでそれに関係するのを利用する。Container Adapter等は https://docs.jboss.org/author/display/ARQ/Container+adapters に載ってる
providedRuntime "org.jboss.arquillian.container:arquillian-glassfish-embedded-3.1:+"
providedRuntime "org.glassfish.main.extras:glassfish-embedded-all:4.0+"
}
※適当なので使ってるやつのバージョン指定は適当にしてますが(ry
src/test/resouces/arquillian.xml
Container Adapterな設定が必要になるので
<?xml version="1.0" encoding="UTF-8" ?>
<arquillian
xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="glassfish-embedded" default="true">
</container>
</arquillian>
あとはテストを書くだけ
SampleTest.java
package sample;
import java.io.File;
import java.net.URL;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
//import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
@RunWith(Arquillian.class)
public class SampleTest {
@ArquillianResource
URL deploymentUrl;
@Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class)
.addPackage("sample")
// .addClasses(Greeter.class, Hoge.class, SampleApplication.class, SampleController.class)
.addAsWebInfResource(new File("src/main/webapp/WEB-INF/beans.xml"))
// .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
.addAsWebInfResource(new File("src/main/webapp/WEB-INF/web.xml"));
}
@RunAsClient
@Test
public void test_greeter() {
String response = target(deploymentUrl.toString() + "/resources/sample/greet")
.request()
.get(String.class);
assertThat(response, is("hoge"));
}
private WebTarget target(String uri) {
return ClientBuilder.newClient().target(uri);
}
}
Arquillianでテストする際には動的にデプロイを作るけど、そのマウントURLが動的(あくまでコンテキストルートが)になるので@ArquillianResourceを使ってURLを取ればそのURLを取得する事が可能
あと@RunAsClientは参考サイトに書いてあるけど、@RunWith(Arquillian.class)をしているテストでは@Testがサーバー上で動くとの事、@RunAsClientはクライアント上で動作するとの事らしい
てな感じでJAX-RS+CDIな構成なテストをJerseyTestじゃなくてArquillianを使って利用する事も出来る。あとremoteなパッケージとかもあるのでそこら辺はまた後日やる予定