現在、 JAX-RS (RESTful WebサービスのJava API)ベースのWebサービスの自動テストを作成する方法を探しています。
基本的に、特定の入力を送信し、期待される応答が得られることを確認する方法が必要です。私はJUnitを介してこれを行うことを望んでいますが、それがどのように達成できるかわかりません。
Webサービスをテストするためにどのようなアプローチを使用していますか?
更新:entzikが指摘したように、Webサービスをビジネスロジックから切り離すことで、ビジネスロジックの単体テストを行うことができます。ただし、正しいHTTPステータスコードなどについてもテストしたいと思います。
Jersey には、ユニットテストの作成を非常に簡単にする優れたRESTfulクライアントAPIが付属しています。 Jerseyに同梱されている例の単体テストを参照してください。このアプローチを使用して、RESTの Apache Camel のサポートをテストします。興味がある場合は テストケースはこちら
REST Assured を試すことができます非常に RESTサービスをテストし、Javaで応答を検証するのは簡単です(JUnitまたはTestNGを使用)。
ジェームズが言ったように。組み込みの テストフレームワーク Jerseyがあります。簡単なHello Worldの例は次のようになります。
maven統合用のpom.xml。 mvn test
を実行すると。フレームワークはグリズリーコンテナーを開始します。依存関係を変更することで、jettyまたはTomcatを使用できます。
...
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.16</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.16</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.16</version>
<scope>test</scope>
</dependency>
</dependencies>
...
ExampleApp.Java
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class ExampleApp extends Application {
}
HelloWorld.Java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/")
public final class HelloWorld {
@GET
@Path("/hello")
@Produces(MediaType.TEXT_PLAIN)
public String sayHelloWorld() {
return "Hello World!";
}
}
HelloWorldTest.Java
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.core.Application;
import static org.junit.Assert.assertEquals;
public class HelloWorldTest extends JerseyTest {
@Test
public void testSayHello() {
final String hello = target("hello").request().get(String.class);
assertEquals("Hello World!", hello);
}
@Override
protected Application configure() {
return new ResourceConfig(HelloWorld.class);
}
}
this サンプルアプリケーションを確認できます。
おそらく、ビジネスロジックを実装するコードをいくつかJavaで記述し、そのためのWebサービスエンドポイントを生成しました。
重要なことは、ビジネスロジックを個別にテストすることです。純粋なJavaコードなので、通常のJUnitテストでそれを行うことができます。
これで、Webサービスパーツはエンドポイントに過ぎないため、生成する配管(スタブなど)がJavaコードと同期していることを確認する必要があります。生成されたWebサービスJavaクライアントを呼び出すJUnitテストを作成します。これにより、Webサービスを更新せずにJava署名を変更したときに通知されます。
Webサービスの配管がビルドごとにビルドシステムによって自動的に生成される場合、エンドポイントをテストする必要はありません(すべて適切に生成されていると仮定)。妄想のレベルに依存します。
質問を投稿した日付からは遅すぎますが、これは同様の質問を持っている他の人にとって有用かもしれないと考えました。 Jerseyには、応答ステータスコードなど、RESTful Webサービスをテストできる Jersey Test Framework というテストフレームワークが付属しています。これを使用して、Grizzly、HTTPServer、EmbeddedGlassFishなどの軽量コンテナでテストを実行できます。また、フレームワークを使用して、GlassFishやTomcatなどの通常のWebコンテナでテストを実行できます。
Alchemy rest client generator をご覧ください。これにより、ジャージークライアントを舞台裏で使用して、JAX-RS Webサービスクラスのプロキシ実装を生成できます。事実上、単純なJava単体テストからのメソッド。HTTP認証も処理します。
簡単にテストを実行する必要がある場合、コード生成は関係ないので便利です。
免責事項:私はこのライブラリの著者です。
Apacheの HTTPClient(http://hc.Apache.org/) を使用してRestful Servicesを呼び出します。 HTTPクライアントライブラリを使用すると、get、post、またはその他の必要な操作を簡単に実行できます。サービスがxmlバインディングにJAXBを使用している場合、JAXBContextを作成して、HTTP要求からの入力と出力をシリアル化および非シリアル化できます。
複雑にしないでおく。 Maven Centralからインポートできる https://github.com/valid4j/http-matchers をご覧ください。
<dependency>
<groupId>org.valid4j</groupId>
<artifactId>http-matchers</artifactId>
<version>1.0</version>
</dependency>
使用例:
// Statically import the library entry point:
import static org.valid4j.matchers.http.HttpResponseMatchers.*;
// Invoke your web service using plain JAX-RS. E.g:
Client client = ClientBuilder.newClient();
Response response = client.target("http://example.org/hello").request("text/plain").get();
// Verify the response
assertThat(response, hasStatus(Status.OK));
assertThat(response, hasHeader("Content-Encoding", equalTo("gzip")));
assertThat(response, hasEntity(equalTo("content")));
// etc...
重要なことは、ビジネスロジックを個別にテストすることです
JAX-RSコードを書いてインターフェースの単体テストをしようとしている人が、何らかの奇妙な、不可解な理由で、プログラムの他の部分を単体テストできるという概念を忘れているとは、決して思いません。ビジネスロジッククラスを含む。明白なことを述べることはほとんど役に立たず、応答もテストする必要があるという点が繰り返し述べられました。
JerseyとRESTEasyの両方にクライアントアプリケーションがあり、RESTEasyの場合は同じ注釈を使用できます(注釈付きインターフェースを除外し、テストのクライアント側とサーバー側で使用することもできます)。
このサービスでできることはRESTではありません。 RESTこのサービスでできること。
私が理解しているように、この問題の作成者の主な目的は、JAX RSレイヤーをビジネスレイヤーから分離することです。そして、最初のものだけを単体テストします。ここで解決しなければならない2つの基本的な問題:
最初のものはArquillianで解決されます。 2つ目は arquillican and mock で完全に説明されています
コードの例を次に示します。別のアプリケーションサーバーを使用する場合は異なる場合がありますが、基本的な考え方と利点が得られることを願っています。
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import com.brandmaker.skinning.service.SomeBean;
/**
* Created by alexandr on 31.07.15.
*/
@Path("/entities")
public class RestBean
{
@Inject
SomeBean bean;
@GET
public String getEntiry()
{
return bean.methodToBeMoked();
}
}
import Java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import com.google.common.collect.Sets;
/**
*/
@ApplicationPath("res")
public class JAXRSConfiguration extends Application
{
@Override
public Set<Class<?>> getClasses()
{
return Sets.newHashSet(RestBean.class);
}
}
public class SomeBean
{
public String methodToBeMoked()
{
return "Original";
}
}
import javax.enterprise.inject.Specializes;
import com.brandmaker.skinning.service.SomeBean;
/**
*/
@Specializes
public class SomeBeanMock extends SomeBean
{
@Override
public String methodToBeMoked()
{
return "Mocked";
}
}
@RunWith(Arquillian.class)
public class RestBeanTest
{
@Deployment
public static WebArchive createDeployment() {
WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war")
.addClasses(JAXRSConfiguration.class, RestBean.class, SomeBean.class, SomeBeanMock.class)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
System.out.println(war.toString(true));
return war;
}
@Test
public void should_create_greeting() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://127.0.0.1:8181/test/res/entities");
//Building the request i.e a GET request to the RESTful Webservice defined
//by the URI in the WebTarget instance.
Invocation invocation = target.request().buildGet();
//Invoking the request to the RESTful API and capturing the Response.
Response response = invocation.invoke();
//As we know that this RESTful Webserivce returns the XML data which can be unmarshalled
//into the instance of Books by using JAXB.
Assert.assertEquals("Mocked", response.readEntity(String.class));
}
}
いくつかのメモ:
希望、それが役立つだろう。