1. 序章

この記事は、@RestClientTestアノテーションの簡単な紹介です。

新しいアノテーションは、SpringアプリケーションでのRESTクライアントのテストを簡素化および高速化するのに役立ちます。

2. SpringBootPre-1.4でのRESTクライアントのサポート

Spring Bootは、多くの自動構成されたSpring Beanに一般的な設定を提供する便利なフレームワークであり、Springアプリケーションの構成に集中する必要がなく、コードとビジネスロジックに集中できます。

しかし、バージョン1.3では、RESTサービスクライアントを作成またはテストする場合、あまり役に立ちません。 RESTクライアントのサポートはそれほど深くありません。

REST APIのクライアントを作成するには、通常、RestTemplateインスタンスが使用されます。 通常、使用する前に構成する必要があり、構成が異なる場合があるため、SpringBootはユニバーサルに構成されたRestTemplateBeanを提供しません。

RESTクライアントのテストについても同じことが言えます。 Spring Boot 1.4.0より前は、SpringRESTクライアントをテストする手順は他のSpringベースのアプリケーションとそれほど変わりませんでした。 MockRestServiceServer インスタンスを作成し、それをテスト対象の RestTemplate インスタンスにバインドして、次のように要求に対する模擬応答を提供します。

RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer =
  MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(requestTo("/greeting"))
  .andRespond(withSuccess());

// Test code that uses the above RestTemplate ...

mockServer.verify();

また、Springコンテナーを初期化し、必要なコンポーネントのみがコンテキストにロードされるようにして、コンテキストのロード時間(したがって、テストの実行時間)を高速化する必要があります。

3. SpringBoot1.4以降の新しいRESTクライアント機能

Spring Boot 1.4では、チームはRESTクライアントの作成とテストを簡素化および高速化するために確固たる努力を払ってきました。

それでは、新機能を確認してみましょう。

3.1. プロジェクトにSpringBootを追加する

まず、プロジェクトでSpring Boot1.4.x以降を使用していることを確認する必要があります。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

最新のリリースバージョンはここにあります。

3.2. RestTemplateBuilder

Spring Bootは、自動構成された RestTemplateBuilder を使用して、 RestTemplates の作成を簡素化し、対応する @RestClientTest アノテーションを使用して、RestTemplateBuilderで構築されたクライアントをテストします。 ]。 RestTemplateBuilderが自動注入された単純なRESTクライアントを作成する方法は次のとおりです。

@Service
public class DetailsServiceClient {

    private final RestTemplate restTemplate;

    public DetailsServiceClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
    }

    public Details getUserDetails(String name) {
        return restTemplate.getForObject("/{name}/details",
          Details.class, name);
    }
}

RestTemplateBuilderインスタンスをコンストラクターに明示的にワイヤリングしていないことに注意してください。 これは、この記事で説明されている暗黙的なコンストラクタインジェクションと呼ばれる新しいSpring機能のおかげで可能になります。

RestTemplateBuilder は、メッセージコンバーター、エラーハンドラー、URIテンプレートハンドラー、基本認証を登録し、必要な追加のカスタマイザーを使用するための便利なメソッドを提供します。

3.3. @RestClientTest

RestTemplateBuilder で構築されたこのようなRESTクライアントをテストするには、@RestClientTestで注釈が付けられたSpringRunner実行テストクラスを使用できます。 このアノテーションは完全な自動構成を無効にし、RESTクライアントテストに関連する構成のみを適用します。 JacksonまたはGSONの自動構成および@JsonComponent Bean。ただし、通常の@ComponentBeanではありません。

@RestClientTest は、JacksonとGSONのサポートが自動構成されていることを確認し、事前構成されたRestTemplateBuilderおよびMockRestServiceServerインスタンスをコンテキストに追加します。 テスト対象のBeanは、@RestClientTestアノテーションのvalueまたはcomponents属性で指定されます。

@RunWith(SpringRunner.class)
@RestClientTest(DetailsServiceClient.class)
public class DetailsServiceClientTest {

    @Autowired
    private DetailsServiceClient client;

    @Autowired
    private MockRestServiceServer server;

    @Autowired
    private ObjectMapper objectMapper;

    @Before
    public void setUp() throws Exception {
        String detailsString = 
          objectMapper.writeValueAsString(new Details("John Smith", "john"));
        
        this.server.expect(requestTo("/john/details"))
          .andRespond(withSuccess(detailsString, MediaType.APPLICATION_JSON));
    }

    @Test
    public void whenCallingGetUserDetails_thenClientMakesCorrectCall() 
      throws Exception {

        Details details = this.client.getUserDetails("john");

        assertThat(details.getLogin()).isEqualTo("john");
        assertThat(details.getName()).isEqualTo("John Smith");
    }
}

まず、 @RunWith(SpringRunner.class)アノテーションを追加して、このテストがSpringRunnerで実行されることを確認する必要があります。

それで、何が新しいのですか?

First @RestClientTest アノテーションを使用すると、テスト対象の正確なサービスを指定できます。この場合は、DetailsServiceClientクラスです。 このサービスはテストコンテキストにロードされ、他のすべては除外されます。

これにより、 DetailsServiceClient インスタンスをテスト内に自動配線し、他のすべてを外部に残して、コンテキストの読み込みを高速化できます。

Second MockRestServiceServer インスタンスも、 @RestClientTest 注釈付きテスト用に構成されているため(そして、 DetailsServiceClient インスタンスにバインドされています) 、注入して使用するだけです。

Finally @RestClientTest のJSONサポートにより、Jacksonの ObjectMapper インスタンスを挿入して、MockRestServiceServerの模擬回答値を準備できます。

あとは、サービスへの呼び出しを実行して結果を確認するだけです。

4. 結論

この記事では、Springで構築されたRESTクライアントの簡単で迅速なテストを可能にする新しい@RestClientTestアノテーションについて説明しました。

この記事のソースコードは、GitHubから入手できます。