複数のMIMEタイプを使用したRESTのテスト
1. 概要
この記事では、複数のメディアタイプ/表現を使用したRESTサービスのテストに焦点を当てます。
APIでサポートされる複数の種類の表現を切り替えることができる統合テストを作成します。 目標は、異なるメディアタイプを要求するだけで、サービスのまったく同じURIを使用して、まったく同じテストを実行できるようにすることです。
2. 目標
REST APIは、1つ以上のメディアタイプを使用して、リソースを表現として公開する必要があります。 The client will set the Accept header to choose the type of representation it asks for from the service.
リソースは複数の表現を持つことができるため、サーバーは正しい表現を選択するメカニズムを実装する必要があります。 これは、コンテンツネゴシエーションとも呼ばれます。
したがって、クライアントがapplication/xmlを要求した場合、リソースのXML表現を取得する必要があります。 また、application/jsonを要求する場合は、JSONを取得する必要があります。
3. テストインフラストラクチャ
まず、マーシャラーのシンプルなインターフェースを定義します。 これは、テストが異なるメディアタイプを切り替えることを可能にする主要な抽象化になります。
public interface IMarshaller {
...
String getMime();
}
次に、何らかの外部設定に基づいて適切なマーシャラーを初期化する方法が必要です。
For this, we’ll use a Spring FactoryBean to initialize the marshaller and a simple property to determine which marshaller to use:
@Component
@Profile("test")
public class TestMarshallerFactory implements FactoryBean {
@Autowired
private Environment env;
public IMarshaller getObject() {
String testMime = env.getProperty("test.mime");
if (testMime != null) {
switch (testMime) {
case "json":
return new JacksonMarshaller();
case "xml":
return new XStreamMarshaller();
default:
throw new IllegalStateException();
}
}
return new JacksonMarshaller();
}
public Class getObjectType() {
return IMarshaller.class;
}
public boolean isSingleton() {
return true;
}
}
これを見てみましょう:
-
まず、Spring 3.1で導入された新しいEnvironment抽象化がここで使用されます。これについて詳しくは、detailed article on using Properties with Springを確認してください。
-
環境からtest.mimeプロパティを取得し、それを使用して、作成するマーシャラーを決定します。ここでは、Java 7switch on String構文が機能しています。
-
次に、プロパティがまったく定義されていない場合のデフォルトのマーシャラーは、JSONサポート用のジャクソンマーシャラーになります
-
最後に–このBeanFactoryは、Spring 3.1でも導入された@Profileサポートを使用しているため、テストシナリオでのみアクティブになります。
それだけです。メカニズムは、test.mimeプロパティの値に基づいてマーシャラーを切り替えることができます。
4. JSONおよびXMLマーシャラー
次に、サポートされているメディアタイプごとに1つずつ、実際のマーシャラーの実装が必要になります。
JSONの場合、基礎となるライブラリとしてJacksonを使用します。
public class JacksonMarshaller implements IMarshaller {
private ObjectMapper objectMapper;
public JacksonMarshaller() {
super();
objectMapper = new ObjectMapper();
}
...
@Override
public String getMime() {
return MediaType.APPLICATION_JSON.toString();
}
}
XMLサポートの場合、マーシャラーはXStreamを使用します。
public class XStreamMarshaller implements IMarshaller {
private XStream xstream;
public XStreamMarshaller() {
super();
xstream = new XStream();
}
...
public String getMime() {
return MediaType.APPLICATION_XML.toString();
}
}
Note that these marshallers are not Spring beans themselves。 その理由は、TestMarshallerFactory;によってSpringコンテキストにブートストラップされるため、コンポーネントを直接作成する必要がないためです。
5. JSONとXMLの両方でサービスを利用する
この時点で、デプロイされたサービスに対して完全な統合テストを実行できるはずです。 マーシャラーの使用は簡単です。テストにIMarshallerを挿入します。
@ActiveProfiles({ "test" })
public abstract class SomeRestLiveTest {
@Autowired
private IMarshaller marshaller;
// tests
...
}
Springは、test.mimeプロパティの値に基づいて、注入する正確なマーシャラーを決定します。
このプロパティの値を指定しない場合、TestMarshallerFactoryはデフォルトのマーシャラーであるJSONマーシャラーにフォールバックします。
6. メイヴンとジェンキンス
MavenがすでにデプロイされているRESTサービスに対して統合テストを実行するように設定されている場合、次を使用して実行できます。
mvn test -Dtest.mime=xml
または、これがビルドでMavenライフサイクルのintegration-testフェーズを使用する場合:
mvn integration-test -Dtest.mime=xml
統合テストを実行するようにMavenビルドを設定する方法の詳細については、Integration Testing with Mavenの記事を参照してください。
Jenkinsでは、次を使用してジョブを構成する必要があります。
This build is parametrized
そして、String parameter:test.mime=xmlが追加されました。 **
一般的なJenkins構成では、展開されたサービスに対して同じセットの統合テストを実行するジョブが必要になります。1つはXMLで、もう1つはJSON表現です。
7. 結論
この記事では、複数の表現で機能するREST APIをテストする方法を示しました。 ほとんどのAPIは、複数の表現の下でリソースを公開するため、これらすべてをテストすることが不可欠です。 すべてのテストでまったく同じテストを使用できるというのは素晴らしいことです。
このメカニズムの完全な実装(実際の統合テストを使用し、XML表現とJSON表現の両方を検証する)は、the GitHub projectにあります。