28

私はJerseyクライアントAPIを呼び出すコードを作成しました。このAPIは、自分の制御できないWebサービスを呼び出します。単体テストで実際のWebサービスを呼び出さないようにします。

ジャージークライアントAPIを呼び出すコードの単体テストを作成するための最良のアプローチは何ですか?ジャージーサーバーAPIを使用してJAX-RSWebサービスを作成してから、単体テストにジャージーテストフレームワークを使用する必要がありますか?または、Jersey Webサービスの呼び出しをモックアウトする必要がありますか?JMockにアクセスできます。または、別のアプローチを試す必要がありますか?

調査中に、さまざまなオプションについて説明しているこのディスカッションを見つけましたが、完全な解決策を見つけました。提案されたJUnitアプローチを示す利用可能なコード例はありますか?ジャージーのドキュメントには何も見つかりませんでした。

関連するソースコードは次のとおりです。

public String getResult(URI uri) throws Exception {
  // error handling code removed for clarity
  ClientConfig clientConfig = new DefaultClientConfig();
  Client client = Client.create(clientConfig);
  WebResource service = client.resource(uri);
  String result = service.accept(accept).get(String.class);
  return result;
}

これが私が合格したいテストコードの例です。(1)有効なURIを渡して有効な文字列を取得し、(2)無効な(何らかの理由で-到達不能または無許可の)URIを渡して例外を取得することをテストしたいと思います。

@Test
public void testGetResult_ValidUri() throws Exception {
  String xml = retriever.getResult(VALID_URI);
  Assert.assertFalse(StringUtils.isBlank(xml));
}

@Test(expected = IllegalArgumentException.class)
public void testGetResult_InvalidUri() throws Exception {
  retriever.getResult(INVALID_URI);
}

上記のすべては、私のコードが何をするかについての簡単な説明です。実際には、その上に2つのURIを受け入れるレイヤーがあり、最初に最初のURIを呼び出そうとし、そのURIが失敗した場合は、2番目のURIを呼び出そうとします。(1)最初のURIが成功し、(2)最初のURIが失敗し、2番目のURIが成功し、(3)両方のURIが失敗する単体テストが必要です。このコードは十分に複雑なので、JUnitを使用してこれらのさまざまなシナリオをテストしたいのですが、これを行うには、実際のスタンドインWebサービスを実行するか、JerseyクライアントAPI呼び出しをモックアウトする必要があります。

4

3 に答える 3

15

サービスコールのモックには、MockitoまたはEasymockを使用してみてください。実際に使用されているこれらのメソッドのみをモックする必要があります。すべてのメソッドをモックする必要はありません。WebResourceクラスのモックオブジェクトを作成してから、メソッド呼び出しをモックで受け入れることができます。

@ BeforeClass / @ Before JUnitテストメソッドに次のように記述します(Mockitoの例)

WebResource res = mock(WebResource.class);
when(res.accept(something)).thenReturn(thatWhatYouWant);

次に、テストでresオブジェクトを実際のオブジェクトであるかのように使用し、その上でモックメソッドを呼び出すことができます。値を返す代わりに、例外をスローすることもできます。Mockitoはかなりクールです。

于 2012-06-12T22:27:54.613 に答える
14

通常、あなたが本当に求めているのは、「Jersey Client DSLを使用する方法で、正しいペイロードとURLパラメーターを使用して正しいURLへの要求を生成するか」です。Mockitoでこれをテストすることは本当に冗長であり、セットアップコードは通常次のようになります。

    when(authentication.queryParam(eq("sa"), anyBoolean())).thenReturn(testAuthentication);
    when(testAuthentication.resolveTemplate("channel", "smf")).thenReturn(testAuthentication);
    when(testAuthentication.request(
            MediaType.APPLICATION_JSON_TYPE)).thenReturn(mockRequestBuilder);
    when(mockRequestBuilder.post(any(Entity.class))).thenReturn(mockResponse);
    when(mockResponse.readEntity(ResponseWrapper.class)).thenReturn(successfulAuthResponse());

そして、これは基本的に単一のRESTリクエスト用です。これは非常に冗長であり、期待される結果をテストする代わりに、JerseyClientDSLを使用する際に正しいと思われる手順を複製しているだけです。

上記の代わりに、簡単なサービスをモックすることを目指します。このために、Jettyサーバーを起動するWireMockを使用しました。ここでは、 「このURLへのリクエストを期待し、このメッセージで応答し、ペイロードがこれであることを確認する」などのスタブを作成できます。

これは統合テストの端にあり、Mockitoを使用するよりも少し遅いことはわかっていますが、実際の結果をテストすることを重視しており、この場合はテストの可読性を重視しています。

WireMockベースのJerseyClientテストのセットアップは次のようになります。

@Test
public void exactUrlOnly() {
    stubFor(get(urlEqualTo("/some/thing"))
            .willReturn(aResponse()
                .withHeader("Content-Type", "text/plain")
                .withBody("Hello world!")));

   assertThat(testClient.get("/some/thing").statusCode(), is(200));
   assertThat(testClient.get("/some/thing/else").statusCode(), is(404));
}
于 2014-10-22T05:17:53.990 に答える
0

同様のサービスを実装し、単体テストのセットアップでHttpServerFactoryを使用してサービスを開始するだけです。

于 2012-06-13T00:53:54.663 に答える