2012-06-12 20 views
25

JerseyクライアントAPIを呼び出すコードを記述しました.JerseyクライアントAPIは、自分のコントロールできないWebサービスを呼び出します。単体テストで実際のWebサービスを呼び出すことは望ましくありません。Jersey Client APIを呼び出すユニットテストコードはどうすればよいですか?

JerseyクライアントAPIを呼び出すコードの単体テストを作成する最適な方法は何ですか? JerseyサーバーAPIを使用してJAX-RS Webサービスを作成し、ユニットテストにJersey Test Frameworkを使用する必要がありますか?または、JerseyのWebサービスコールを模倣すべきですか?私はJMockにアクセスできます。それとも別のアプローチを試みるべきですか?

私の研究では、さまざまなオプションについて説明しているthis discussionが見つかりましたが、私は完全な解決策を見つけました。提案されているJUnitアプローチを示すコード例がありますか?私はJerseyの文書には何も見つかりませんでした。ここ

は、関連するソースコードである:ここ

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(到達不能または許可されていない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呼び出しをモックアウトする必要があります。

+0

何まさにあなたがこの方法でテストしたいですか?テストに合格した基準は何ですか? – dbf

+0

ユニットテストをしたい場合は、適切な機能サービスが必要です。 – iDroid

+0

@dbf私は、(1)有効なURIを渡して有効な文字列を取得し、(2)無効な(何らかの理由で - 到達不能または許可されていない)URIを渡して例外を取得するバック。 – BennyMcBenBen

答えて

12

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

は(Mockito例)のようなもの

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

そして、それが本当の目的であったかのように、あなたのテストで使用すると、解像度のオブジェクトを使用することができ、その上にモックメソッドを呼び出しを記述します。値を返す代わりに、例外をスローすることもできます。 Mockitoはかなりクールです。

+1

これは正解です。 Jerseyコードがすでに動作していることを知っているときに、Jerseyコードをテストするために、全体のWebサービスを作成することに努力しています。私は自分のコードをテストしたい。私はジャージーコードの呼び出しを別のクラスにリファクタリングし、セッターを追加して、新しいクラスを模倣しなくてはなりませんでした。これは完全に機能し、実際にテストしたいさまざまなシナリオをテストすることができました。私のチームはJMockを使用していますので、これを使用して終了しましたが、どんなモックフレームワークでも可能です。 – BennyMcBenBen

+0

私はMockitoのウェブサイトが「あなたが所有していないタイプを模倣しないでください!」と述べているので、少し混乱しています。私たちは何を嘲笑するのか、それとも嘲ることができないのかについて、どこに線を描くのでしょうより良い方法がありますか? –

0

単体でサービスを実装し、単体テストセットアップでHttpServerFactoryを使用してサービスを開始してください。

11

通常、実際に何をしているのはです。正しいペイロードとURLパラメータを持つ正しいURLへのリクエストをJersey Client DSLが生成します。 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()); 

をそして、これは単に1つのREST要求のための基本的です。あまりにも冗長で、期待される結果をテストするのではなく、Jersey Client DSLを使用する上で正しいと思われる手順を複製するだけです。

上記の代わりに、私は簡単なサービスを嘲笑することを目指します。このため私はWireMockを使ってJettyサーバを起動しました。のようなものをスタブすることができます。 "このURLへのリクエストを期待し、このメッセージで応答し、ペイロードがこれであることを確認してください"

これはインテグレーションテストでは縁があり、Mockitoを使用するよりも少し遅いですが、私は実際の結果をテストすることを大切にしています。この場合、テストの可読性をより重視します。ジャージークライアントのテストに基づくWireMockため

セットアップは次のようになります。

@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)); 
} 
+0

+1 for WireMock - 素晴らしいツール。私の場合、MockitoはWireMockで解決したWebResource.Builder(最終版)をモックできませんでした。 – denismo

関連する問題