Spring Cloud契約のイントロ

1前書き

  • Spring Cloud Contract は、簡単に言うとhttps://martinfowler.com/articles/consumerDrivenContracts.html[Consumer-Drivenを書くのに役立つプロジェクトです。契約(CDC)]。**

これにより、HTTPベースとメッセージベースの両方の対話において、分散システムで Producer Consumer の間の契約が保証されます。

この簡単な記事では、Spring Cloud Contractのプロデューサー側とコンシューマー側のテストケースをHTTPインタラクションを通じて作成する方法について説明します。

2プロデューサー - サーバーサイド

プロデューサー側のCDCを EvenOddController の形式で記述します。これは number パラメーターが偶数か奇数かを示すだけです。

@RestController
public class EvenOddController {

    @GetMapping("/validate/prime-number")
    public String isNumberPrime(@RequestParam("number") Integer number) {
        return Integer.parseInt(number) % 2 == 0 ? "Even" : "Odd";
    }
}

2.1. Mavenの依存関係

プロデューサー側には、https://search.maven.org/classic/#search%7C1%7Cg%3A%22org.springframework.cloud%22%20AND%20a%3A%22spring-cloudが必要です-starter-contract-verifier%22[ spring-cloud-starter-contract-verifier ]依存関係:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-contract-verifier</artifactId>
    <version>Edgware.SR1</version>
    <scope>test</scope>
</dependency>

そして、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.cloud%22%20AND%20a%3A%22spring-cloud-contract-を設定する必要があります次のセクションで説明するように、maven-plugin%22[ spring-cloud-contract-maven-plugin ]に基本テストクラスの名前を付けます。

<plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>1.2.2.RELEASE</version>
    <extensions>true</extensions>
    <configuration>
        <baseClassForTests>
            com.baeldung.spring.cloud.springcloudcontractproducer.BaseTestClass
        </baseClassForTests>
    </configuration>
</plugin>

2.2. プロデューサー側の設定

テストパッケージにSpringのコンテキストをロードする基本クラスを追加する必要があります。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@DirtiesContext
@AutoConfigureMessageVerifier
public class BaseTestClass {

    @Autowired
    private EvenOddController evenOddController;

    @Before
    public void setup() {
        StandaloneMockMvcBuilder standaloneMockMvcBuilder
          = MockMvcBuilders.standaloneSetup(evenOddController);
        RestAssuredMockMvc.standaloneSetup(standaloneMockMvcBuilder);
    }
}
  • /src/test/resources/contract/ パッケージに、 shouldReturnEvenWhenRequestParamIsEven.groovy ファイルのように、テストスタブを追加します。

import org.springframework.cloud.contract.spec.Contract
Contract.make {
    description "should return even when number input is even"
    request{
        method GET()
        url("/validate/prime-number") {
            queryParameters {
                parameter("number", "2")
            }
        }
    }
    response {
        body("Even")
        status 200
    }
}

ビルドを実行すると、プラグインは BaseTestClass ** を拡張する ContractVerifierTest という名前のテストクラスを自動的に生成し、それを /target/generated-test-sources/contract/ に格納します。

テストメソッドの名前は、Groovyのテストスタブの名前と連結した接頭辞「 validate 」に由来します。上記のGroovyファイルの場合、生成されたメソッド名は “ validate shouldReturnEvenWhenRequestParamIsEven” __になります。

この自動生成されたテストクラスを見てみましょう。

public class ContractVerifierTest extends BaseTestClass {

@Test
public void validate__shouldReturnEvenWhenRequestParamIsEven() throws Exception {
   //given:
    MockMvcRequestSpecification request = given();

   //when:
    ResponseOptions response = given().spec(request)
      .queryParam("number","2")
      .get("/validate/prime-number");

   //then:
    assertThat(response.statusCode()).isEqualTo(200);

   //and:
    String responseBody = response.getBody().asString();
    assertThat(responseBody).isEqualTo("Even");
}
  • ビルドはスタブjarをローカルのMavenリポジトリにも追加して、消費者が使用できるようにします。

スタブは stubs/mapping/ の下の出力フォルダーにあります。

3消費者 - クライアント側

  • 私たちのCDCの消費者側は、契約を維持するために HTTP対話を通して 生産者側によって生成されたスタブを消費するでしょう、それで 生産者側のどんな変更も契約を破るでしょう

生成されたスタブから応答を取得するためのHTTPリクエストを作成する BasicMathController、 を追加します。

@RestController
public class BasicMathController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/calculate")
    public String checkOddAndEven(@RequestParam("number") Integer number) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");

        ResponseEntity<String> responseEntity = restTemplate.exchange(
          "http://localhost:8090/validate/prime-number?number=" + number,
          HttpMethod.GET,
          new HttpEntity<>(httpHeaders),
          String.class);

        return responseEntity.getBody();
    }
}

3.1. Mavenの依存関係

私たちの消費者のために、私たちはhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22org.springframework.cloud%22%20AND%20a%3A%22spring-を追加する必要があります。 cloud-contract-wiremock%22[ spring-cloud-contract-wiremock ]およびhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.cloud%22%20AND% 20a%3A%22春のクラウドコントラクトスタブランナー%22[__春のクラウドコントラクトスタブランナー]の依存関係:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-wiremock</artifactId>
    <version>1.2.2.RELEASE</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-stub-runner</artifactId>
    <version>1.2.2.RELEASE</version>
    <scope>test</scope>
</dependency>

3.2. 消費者サイドの設定

今度は、スタブランナーを設定します。これで、ローカルのMavenリポジトリで利用可能なスタブについてコンシューマに通知します。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@AutoConfigureStubRunner(
  workOffline = true,
  ids = "com.baeldung.spring.cloud:spring-cloud-contract-producer:+:stubs:8090")
public class BasicMathControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void given__WhenPassEvenNumberInQueryParam__ThenReturnEven()
      throws Exception {

        mockMvc.perform(MockMvcRequestBuilders.get("/calculate?number=2")
          .contentType(MediaType.APPLICATION__JSON))
          .andExpect(status().isOk())
          .andExpect(content().string("Even"));
    }
}

@ AutoConfigureStubRunner アノテーションの ids プロパティは、次のように指定します。

  • com.baeldung.spring.cloud - アーティファクトの groupId

  • クラウドクラウド契約プロデューサ - プロデューサの artifactId

スタブジャー ** 8090 - 生成されたスタブが実行されるポート

4契約が切れたとき

生産者側で、消費者側を更新せずに契約に直接影響を与えるような変更を加えた場合、 これは契約の失敗を招く可能性があります

たとえば、プロデューサー側で EvenOddController リクエストURIを /validate/change/prime-number に変更するとします。

この変更についてコンシューマに通知しない場合でも、コンシューマはその要求を /validate/prime-number URIに送信し、コンシューマ側のテストケースは org.springframework.web.client.HttpClientErrorExceptionをスローします。404 Not Found

5概要

Spring Cloud Contractがサービスコンシューマとプロデューサの間の契約の維持にどのように役立つかを確認したので、契約を破ることを心配せずに新しいコードをプッシュすることができます。

そして、いつものように、このチュートリアルの完全な実装はhttps://github.com/eugenp/tutorials/tree/master/spring-cloud/spring -cloud-contract[over on GitHub]にあります。