CLOVER🍀

That was when it all began.

ArquillianでJAX-RSのテスト

前に、Arquillianでやった、テストの続き。前回はEJBJPAだけだったので、今度はJAX-RSのテストをやってみます。

といっても、ほとんどここのマネではありますが。

arquillian-showcase / jaxrs
https://github.com/arquillian/arquillian-showcase/tree/master/jaxrs

大きく違うのは、Scala+sbtでやったことと、RESTEasyのProxyFactoryは妥協したことでしょうか…。

準備

sbtの設定から。
build.sbt

name := "arquillian-jax-rs"

version := "0.0.1-SNAPSHOT"

scalaVersion := "2.10.3"

organization := "littlewings"

resolvers += "Public JBoss Group" at "http://repository.jboss.org/nexus/content/groups/public-jboss"

fork in Test := true

envVars in Test += ("JBOSS_HOME", "/path/to/jboss-as-7.1.1.Final")

libraryDependencies ++= Seq(
  "org.jboss.spec" % "jboss-javaee-web-6.0" % "3.0.2.Final" % "provided",
  "org.jboss.as" % "jboss-as-arquillian-container-managed" % "7.1.1.Final" % "test" excludeAll(
    ExclusionRule(organization = "org.jboss.shrinkwrap"),
    ExclusionRule(organization = "org.jboss.shrinkwrap.descriptors")
  ),
  "org.jboss.arquillian.junit" % "arquillian-junit-container" % "1.1.1.Final" % "test" excludeAll(
    ExclusionRule(organization = "org.jboss.shrinkwrap"),
    ExclusionRule(organization = "org.jboss.shrinkwrap.descriptors")
  ),
  "org.jboss.shrinkwrap" % "shrinkwrap-api" % "1.0.0-cr-1" % "test",
  "org.jboss.shrinkwrap" % "shrinkwrap-impl-base" % "1.1.2" % "test",
  "org.jboss.shrinkwrap.descriptors" % "shrinkwrap-descriptors-spi" % "2.0.0-alpha-3" % "test",
  "org.jboss.shrinkwrap.resolver" % "shrinkwrap-resolver-depchain" % "2.0.1" % "test" excludeAll(
    ExclusionRule(organization = "org.jboss.shrinkwrap")
  ),
  "org.jboss.resteasy" % "resteasy-jaxrs" % "2.3.2.Final" % "test",
  "junit" % "junit" % "4.11" % "test",
  "com.novocode" % "junit-interface" % "0.10" % "test"
)

今回は、前回慌てて通したライブラリの依存関係を整理すべく、MavenでArquillianの依存関係をdependenc:treeで見ながらやりましたが、結局同じような結果になりました。

JAX-RSの有効化。
src/main/scala/javaee6/web/jaxrs/SimpleApplication.scala

package javaee6.web.jaxrs

import javax.ws.rs.ApplicationPath
import javax.ws.rs.core.Application

@ApplicationPath("/rest")
class SimpleApplication extends Application {
}

テスト対象のクラス。
src/main/scala/javaee6/web/jaxrs/SimpleResource.scala

package javaee6.web.jaxrs

import javax.ws.rs.{GET, Path, Produces}
import javax.ws.rs.core.MediaType

@Path("simple")
class SimpleResource {
  @GET
  @Produces(Array(MediaType.TEXT_PLAIN))
  def hello: String =
    "Hello World"
}

ごくごく、簡単なものにしました。

テストコード

Arquillianを使ったテストコードは、こちら。
src/test/scala/javaee6/web/jaxrs/SimpleResourceTest.scala

package javaee6.web.jaxrs

import java.net.URL

import javax.ws.rs.ApplicationPath
import javax.ws.rs.core.{MediaType, Response}

import org.jboss.arquillian.container.test.api.{Deployment, RunAsClient}
import org.jboss.arquillian.junit.Arquillian
import org.jboss.arquillian.test.api.ArquillianResource
import org.jboss.resteasy.client.{ClientRequest, ClientResponse}
import org.jboss.resteasy.plugins.providers.RegisterBuiltin
import org.jboss.resteasy.spi.ResteasyProviderFactory
import org.jboss.shrinkwrap.api.ShrinkWrap
import org.jboss.shrinkwrap.api.spec.WebArchive
import org.jboss.shrinkwrap.resolver.api.maven.Maven

import org.junit.{BeforeClass, Test}
import org.junit.runner.RunWith

import org.junit.Assert._
import org.hamcrest.CoreMatchers._

@RunWith(classOf[Arquillian])
@RunAsClient
class SimpleResourceTest {
  private val resourcePrefix =
    classOf[SimpleApplication]
      .getAnnotation(classOf[ApplicationPath])
      .value
      .substring(1)

  @ArquillianResource
  private var deploymentUrl: URL = _

  @Test
  def helloTest: Unit = {
    val request = new ClientRequest(deploymentUrl + resourcePrefix + "/simple")
    request.header("Accept", MediaType.TEXT_PLAIN)
    val response = request.get(classOf[String])
    assertThat(response.getStatus, is(Response.Status.OK.getStatusCode))
    assertThat(response.getEntity, is("Hello World"))
  }
}

object SimpleResourceTest {
  @Deployment
  def createDeployment: WebArchive =
    ShrinkWrap
      .create(classOf[WebArchive], "arquillian-test.war")
      .addPackages(true, "javaee6.web.jaxrs")
      .addAsLibraries {
        Maven
          .resolver
          .resolve("org.scala-lang:scala-library:2.10.3")
          .withTransitivity
          .asFile: _*
      }
}

まあ、RESTEasyのクライアントAPIを使ってリクエストを投げているだけ、とも言えますが。showcaseのものも、そんな感じでしたしね。
JAX-RS 2.0のクライアントAPIは、WildFlyが出たら使います

アプリケーションサーバから見てクライアントとして動作させるためか、テストクラスに@RunAsClientアノテーションが付いていることがポイントみたいです。

@RunWith(classOf[Arquillian])
@RunAsClient
class SimpleResourceTest {

その他、

  @ArquillianResource
  private var deploymentUrl: URL = _

でデプロイ先の基本的なURLが取れることと、JAX-RSの設定をうまく使ってパスを組み立てるのは、なるほどなーと思いました。

  private val resourcePrefix =
    classOf[SimpleApplication]
      .getAnnotation(classOf[ApplicationPath])
      .value
      .substring(1)

あとは、テストを実行するだけ。

> test

簡単ではありますが、こんなところで。近いうちに、Remoteモードもやらないと。Scalaのままで、できるかな?