Maven プロジェクト
Maven プラグインの追加
Spring Cloud Contract BOM を追加するには、pom.xml
ファイルに次のセクションを含めます。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-dependencies</artifactId>
<version>${spring-cloud-contract.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
次に、次のように Spring Cloud Contract Verifier
Maven プラグインを追加します。
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<packageWithBaseClasses>com.example.fraud</packageWithBaseClasses>
</configuration>
</plugin>
詳細については、spring-cloud-contract-maven-plugin/index.html[Spring Cloud Contract Maven プラグイン Documentation] を参照してください。
場合によっては、選択した IDE に関係なく、target/generated-test-source
フォルダーが IDE のクラスパスに表示されないことがあります。常に存在するようにするには、pom.xml
に次のエントリを追加します。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-test-sources/contracts/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Maven と安心の 2.0
デフォルトでは、Rest Assured 3.x がクラスパスに追加されます。ただし、次のようにプラグインのクラスパスに追加することで Rest Assured 2.x を使用できます。
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<packageWithBaseClasses>com.example</packageWithBaseClasses>
</configuration>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-verifier</artifactId>
<version>${spring-cloud-contract.version}</version>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>2.5.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>spring-mock-mvc</artifactId>
<version>2.5.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</plugin>
<dependencies>
<!-- all dependencies -->
<!-- you can exclude rest-assured from spring-cloud-contract-verifier -->
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>2.5.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>spring-mock-mvc</artifactId>
<version>2.5.0</version>
<scope>test</scope>
</dependency>
</dependencies>
こうすることで、プラグインは Rest Assured 2.x がクラスパス上に存在することを自動的に確認し、それに応じてインポートを変更します。
Maven のスナップショットバージョンとマイルストーンバージョンの使用
スナップショットバージョンとマイルストーンバージョンを使用するには、次のセクションを pom.xml
に追加する必要があります。
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
スタブの追加
デフォルトでは、Spring Cloud Contract Verifier は src/test/resources/contracts
ディレクトリでスタブを検索します。スタブ定義を含むディレクトリはクラス名として扱われ、各スタブ定義は単一のテストとして扱われます。テストクラス名として使用されるディレクトリが少なくとも 1 つ含まれていることを前提としています。ネストされたディレクトリが複数のレベルにある場合は、最後のディレクトリを除くすべてがパッケージ名として使用されます。次の構造を考えてみましょう。
src/test/resources/contracts/myservice/shouldCreateUser.groovy
src/test/resources/contracts/myservice/shouldReturnUser.groovy
その構造を考慮して、Spring Cloud Contract Verifier は 2 つのメソッドを使用して defaultBasePackage.MyService
という名前のテストクラスを作成します。
shouldCreateUser()
shouldReturnUser()
プラグインの実行
generateTests
プラグインゴールは、generate-test-sources
と呼ばれるフェーズで呼び出されるように割り当てられています。これをビルドプロセスの一部にしたい場合は、何もする必要はありません。テストを生成するだけの場合は、generateTests
ゴールを呼び出します。
Maven からスタブを実行する場合は、次のように、spring.cloud.contract.verifier.stubs
システムプロパティとして実行するスタブを指定して run
ゴールを呼び出します。
mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:run \ -Dspring.cloud.contract.verifier.stubs="com.acme:service-name"
プラグインの設定
デフォルトの構成を変更するには、次のようにプラグイン定義または execution
定義に configuration
セクションを追加します。
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>convert</goal>
<goal>generateStubs</goal>
<goal>generateTests</goal>
</goals>
</execution>
</executions>
<configuration>
<basePackageForTests>org.springframework.cloud.verifier.twitter.place</basePackageForTests>
<baseClassForTests>org.springframework.cloud.verifier.twitter.place.BaseMockMvcSpec</baseClassForTests>
</configuration>
</plugin>
構成オプション
testMode
: 受け入れテストのモードを定義します。デフォルトでは、モードはMockMvc
で、Spring の MockMvc に基づいています。これをWebTestClient
、JaxRsClient
、またはExplicit
(実際の HTTP 呼び出しの場合) に変更することもできます。basePackageForTests
: 生成されたすべてのテストの基本パッケージを指定します。設定されていない場合、値はbaseClassForTests
のパッケージおよびpackageWithBaseClasses
から選択されます。これらの値がどちらも設定されていない場合、値はorg.springframework.cloud.contract.verifier.tests
に設定されます。ruleClassForTests
: 生成されたテストクラスに追加するルールを指定します。baseClassForTests
: 生成されたすべてのテストの基本クラスを作成します。デフォルトでは、Spock クラスを使用する場合、クラスはspock.lang.Specification
です。contractsDirectory
: Groovyn DSL で作成された契約を含むディレクトリを指定します。デフォルトのディレクトリは/src/test/resources/contracts
です。generatedTestSourcesDir
: Groovy DSL から生成されたテストを配置するテストソースディレクトリを指定します。デフォルトでは、その値は$buildDir/generated-test-sources/contracts
です。generatedTestResourcesDir
: 生成されたテストで使用されるリソースのテストリソースディレクトリを指定します。testFramework
: 使用するターゲットテストフレームワークを指定します。現在、Spock、JUnit 4 (TestFramework.JUNIT
)、および JUnit 5 がサポートされており、JUnit 4 がデフォルトのフレームワークです。packageWithBaseClasses
: すべての基本クラスが存在するパッケージを定義します。この設定はbaseClassForTests
よりも優先されます。この規則では、(たとえば)src/test/resources/contract/foo/bar/baz/
に契約があり、packageWithBaseClasses
プロパティの値をcom.example.base
に設定した場合、Spring Cloud Contract Verifier はcom.example.base
パッケージにBarBazBase
クラスがあると想定します。つまり、システムはパッケージの最後の 2 つの部分 (存在する場合) を取得し、接尾辞としてBase
を持つクラスを形成します。baseClassMappings
:contractPackageRegex
(契約が存在するパッケージに対してチェックされる) およびbaseClassFQN
(一致する契約の基本クラスの完全修飾名にマップされる) を提供する基本クラスマッピングのリストを指定します。例:src/test/resources/contract/foo/bar/baz/
に契約があり、.* → com.example.base.BaseClass
プロパティをマップする場合、これらの契約から生成されたテストクラスはcom.example.base.BaseClass
を継承します。この設定はpackageWithBaseClasses
およびbaseClassForTests
よりも優先されます。contractsProperties
: Spring Cloud Contract コンポーネントに渡されるプロパティを含むマップ。これらのプロパティは、(たとえば) 組み込みまたはカスタムのスタブダウンローダーによって使用される可能性があります。failOnNoContracts
: 有効にすると、契約が見つからなかった場合に例外がスローされます。デフォルトはtrue
です。failOnInProgress
:true
に設定すると、進行中の契約が見つかると、ビルドが中断されます。プロデューサー側では、進行中の契約があるという事実を明確にし、コンシューマー側で偽陽性の検査結果が生じる可能性があることを考慮する必要があります。デフォルトはtrue
です。incrementalContractTests
: 有効にすると、最後のビルド以降に契約が変更された場合にのみテストが作成されます。デフォルトはtrue
です。incrementalContractStubs
: 有効にすると、最後のビルド以降に契約が変更された場合にのみスタブが作成されます。デフォルトはtrue
です。incrementalContractStubsJar
: 有効にすると、最後のビルド以降にスタブが変更された場合にのみ、スタブ jar が作成されます。デフォルトはtrue
です。*httpPort
: スタブを提供する WireMock サーバーの HTTP ポート。現在、spring.cloud.contract.verifier.http.port
プロパティは、ディレクトリからスタブを提供する場合にのみ機能します。それ以外の場合、スタブ ID を指定するときは、ID 文字列にポートを含める必要があります。*skip
: ベリファイアの実行をバイパスするには、これをtrue
に設定します。*skipTestOnly
: 検証テストの生成をバイパスするには、これをtrue
に設定します。*stubs
: ダウンロードおよび実行されるスタブのリスト (コロン区切りの Ivy 表記)。*minPort
: スタブを開始する最小のポートを指定します。*maxPort
: スタブを開始する最大ポートを指定します。*waitForKeyPressed
: スタブの開始後にユーザーがキーを押すまでプラグインが待機するかどうかを指定します。*stubsClassifier
: スタブアーティファクトによって使用される分類子を指定します。
Maven リポジトリから契約定義をダウンロードする場合は、次のオプションを使用できます。
contractDependency
: すべてのパッケージ化された契約を含む契約の依存関係。contractsPath
: パッケージ化された契約を使用した JAR 内の具体的な契約へのパス。デフォルトはgroupid/artifactid
で、gropuid
はスラッシュで区切られます。contractsMode
: スタブを検索して登録するモードを選択します。deleteStubsAfterTest
:false
に設定されている場合は、ダウンロードされた契約を一時ディレクトリから削除しないでください。contractsRepositoryUrl
: 契約のあるアーティファクトを含むリポジトリへの URL。付属していない場合は、現行の Maven のものをご使用ください。contractsRepositoryUsername
: 契約を使用してリポジトリに接続するために使用されるユーザー名。contractsRepositoryPassword
: 契約を使用してリポジトリに接続するために使用されるパスワード。contractsRepositoryProxyHost
: 契約を使用してリポジトリに接続するために使用されるプロキシホスト。contractsRepositoryProxyPort
: 契約を使用してリポジトリに接続するために使用されるプロキシポート。
スナップショットではない、明示的に提供されたバージョンのみをキャッシュします (たとえば、+
または 1.0.0.BUILD-SNAPSHOT
はキャッシュされません)。デフォルトでは、この機能はオンになっています。
次のリストでは、プラグインで有効にできる実験的な機能について説明します。
convertToYaml
: すべての DSL を宣言型 YAML 形式に変換します。これは、Groovy DSL で外部ライブラリを使用する場合に非常に役立ちます。この機能をオンにすると (true
に設定すると)、コンシューマー側でライブラリの依存関係を追加する必要がなくなります。assertJsonSize
: 生成されたテストで JSON 配列のサイズを確認できます。この機能はデフォルトでは無効になっています。
すべてのテストに対する単一の基本クラス
Spring Cloud Contract Verifier をデフォルト (MockMvc
) で使用する場合、生成されるすべての受け入れテストの基本仕様を作成する必要があります。このクラスでは、検証する必要があるエンドポイントを指す必要があります。次の例は、その方法を示しています。
import org.mycompany.ExampleSpringController
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
import spock.lang.Specification
class MvcSpec extends Specification {
def setup() {
RestAssuredMockMvc.standaloneSetup(new ExampleSpringController())
}
}
必要に応じて、次の例に示すようにコンテキスト全体をセットアップすることもできます。
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")
public abstract class BaseTestClass {
@Autowired
WebApplicationContext context;
@Before
public void setup() {
RestAssuredMockMvc.webAppContextSetup(this.context);
}
}
EXPLICIT
モードを使用する場合は、通常の統合テストで行う場合と同様に、基本クラスを使用してテスト対象のアプリ全体を初期化できます。次の例は、その方法を示しています。
import io.restassured.RestAssured;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")
public abstract class BaseTestClass {
@LocalServerPort
int port;
@Before
public void setup() {
RestAssured.baseURI = "http://localhost:" + this.port;
}
}
JAXRSCLIENT
モードを使用する場合、この基本クラスには protected WebTarget webTarget
フィールドも含まれている必要があります。現時点では、JAX-RS API をテストする唯一の方法は、Web サーバーを起動することです。
契約に異なる基本クラスを使用する
基本クラスが契約間で異なる場合は、自動生成されたテストによってどのクラスを継承する必要があるかを Spring Cloud Contract プラグインに指示できます。次の 2 つのオプションがあります。
packageWithBaseClasses
の値を指定することにより、規則に従ってください。baseClassMappings
との明示的なマッピングを提供する
慣例により
この規則では、(たとえば) src/test/resources/contract/foo/bar/baz/
に契約があり、packageWithBaseClasses
プロパティの値を com.example.base
に設定すると、Spring Cloud Contract Verifier は com.example.base
パッケージに BarBazBase
クラスがあると想定します。つまり、システムはパッケージの最後の 2 つの部分 (存在する場合) を取得し、Base
サフィックスを持つクラスを形成します。このルールは baseClassForTests
よりも優先されます。次の例は、contracts
クロージャでどのように動作するかを示しています。
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<packageWithBaseClasses>hello</packageWithBaseClasses>
</configuration>
</plugin>
マッピングによる
契約のパッケージの正規表現を、一致する契約の基本クラスの完全修飾名に手動でマップできます。それぞれが contractPackageRegex
から baseClassFQN
へのマッピングを取る baseClassMapping
オブジェクトで構成される baseClassMappings
というリストを提供する必要があります。次の例を考えてみましょう。
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<baseClassForTests>com.example.FooBase</baseClassForTests>
<baseClassMappings>
<baseClassMapping>
<contractPackageRegex>.*com.*</contractPackageRegex>
<baseClassFQN>com.example.TestBase</baseClassFQN>
</baseClassMapping>
</baseClassMappings>
</configuration>
</plugin>
次の 2 つの場所で契約があると仮定します。
src/test/resources/contract/com/
src/test/resources/contract/foo/
baseClassForTests
を提供することで、マッピングが成功しなかった場合のフォールバックが得られます。(フォールバックとして packageWithBaseClasses
を提供することもできます) こうすることで、src/test/resources/contract/com/
契約から生成されたテストは com.example.ComBase
を継承し、残りのテストは com.example.FooBase
を継承します。
生成されたテストの呼び出し
Spring Cloud Contract Maven プラグインは、/generated-test-sources/contractVerifier
というディレクトリに検証コードを生成し、このディレクトリを testCompile
ゴールにアタッチします。
Groovy Spock コードの場合、次を使用できます。
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<testSources>
<testSource>
<directory>${project.basedir}/src/test/groovy</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
<testSource>
<directory>${project.build.directory}/generated-test-sources/contractVerifier</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
</testSources>
</configuration>
</plugin>
プロバイダー側が定義された契約に準拠していることを確認するには、mvn generateTest test
を呼び出す必要があります。
スタブを SCM にプッシュする
SCM (ソース管理管理) リポジトリを使用して契約とスタブを保持する場合は、スタブをリポジトリにプッシュする手順を自動化することができます。これを行うには、pushStubsToScm
ゴールを追加できます。次の例は、その方法を示しています。
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- Base class mappings etc. -->
<!-- We want to pick contracts from a Git repository -->
<contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>
<!-- We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts -->
<contractDependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</contractDependency>
<!-- The contracts mode can't be classpath -->
<contractsMode>REMOTE</contractsMode>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<!-- By default we will not push the stubs back to SCM,
you have to explicitly add it as a goal -->
<goal>pushStubsToScm</goal>
</goals>
</execution>
</executions>
</plugin>
SCM スタブダウンローダーの使用には、<configuration><contractsProperties>
マップ、システムプロパティ、または環境変数を介して渡すことができるすべての構成オプションが表示されます。たとえば、デフォルトの代わりに具体的な ブランチを指定してチェックアウトできます。
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- Base class mappings etc. -->
<!-- We want to pick contracts from a Git repository -->
<contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>
<contractsProperties>
<git.branch>another_branch</git.branch>
</contractsProperties>
<!-- We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts -->
<contractDependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</contractDependency>
<!-- The contracts mode can't be classpath -->
<contractsMode>REMOTE</contractsMode>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<!-- By default we will not push the stubs back to SCM,
you have to explicitly add it as a goal -->
<goal>pushStubsToScm</goal>
</goals>
</execution>
</executions>
</plugin>
Maven プラグインと STS
次の図は、STS の使用時に発生する可能性のある例外を示しています。
エラーマーカーをクリックすると、次のような内容が表示されるはずです。
plugin:1.1.0.M1:convert:default-convert:process-test-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
cloud-contract-maven-plugin:1.1.0.M1:convert failed. at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:145) at
org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:331) at org.eclipse.m2e.core.internal.embedder.MavenImpl$11.call(MavenImpl.java:1362) at
...
org.eclipse.core.internal.jobs.Worker.run(Worker.java:55) Caused by: java.lang.NullPointerException at
org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseIncrementalBuildContext.hasDelta(EclipseIncrementalBuildContext.java:53) at
org.sonatype.plexus.build.incremental.ThreadBuildContext.hasDelta(ThreadBuildContext.java:59) at
この課題を解決するには、pom.xml
に次のセクションを追加します。
<build>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<versionRange>[1.0,)</versionRange>
<goals>
<goal>convert</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
Spock テストを備えた Maven プラグイン
Spock フレームワーク (英語) を選択して、Maven と Gradle の両方で自動生成された契約検証テストを作成および実行できます。ただし、Gradle の使用は簡単ですが、Maven では、テストを適切にコンパイルして実行するために追加のセットアップが必要です。
まず、GMavenPlus [GitHub] (英語) プラグインなどのプラグインを使用して、Groovy をプロジェクトに追加する必要があります。GMavenPlus プラグインでは、基本テストクラスが定義されているパスと生成された契約 テストが追加されたパスの両方を含むテストソースを明示的に設定する必要があります。次の例 (英語) は、そのメソッドを示しています。
テストクラス名の末尾に Spec
を付けるという Spock の規則を守る場合は、次の例 (英語) に示すように、Maven Surefire プラグインのセットアップも調整する必要があります。