1. 序章

この記事では、Spring Bootを使用して構築されたSOAPWebサービスの統合テストを作成する方法を説明します。

アプリケーションクラスの単体テストの記述方法はすでに知っています。また、 Spring Boot でのテストに関するチュートリアルでは、一般的なテストの概念についてすでに説明しました。 したがって、ここでは、@WebServiceServerTestを使用したWebサービスレイヤーのみの統合テストに焦点を当てます。

2. SpringWebサービスのテスト

Spring Webサービスでは、エンドポイントはサーバー側のサービス実装の重要な概念です。 特殊な@Endpointアノテーションは、アノテーションが付けられたクラスをWebサービスエンドポイントとしてマークします。 重要なことに、これらのエンドポイントは、XML要求メッセージを受信し、必要なビジネスロジックを呼び出し、結果を応答メッセージとして返す役割を果たします。

2.1. SpringWebサービステストのサポート

このようなエンドポイントをテストするために、必要な引数またはモックを渡すことで単体テストを簡単に作成できます。 ただし、主な欠点は、これが実際にネットワーク経由で送信されるXMLメッセージのコンテンツをテストしないことです。 別のアプローチは、メッセージのXMLコンテンツを検証する統合テストを作成することです

Spring Web Services 2.0では、このようなエンドポイントの統合テストのサポートが導入されました。 このサポートを提供するコアクラスはMockWebServiceClientです。 Springアプリケーションコンテキストで構成されている適切なエンドポイントにXMLメッセージを送信するための流暢なAPIを提供します。 さらに、応答の期待値を設定し、応答XMLを検証し、エンドポイントの完全な統合テストを実行できます。

ただし、これにはアプリケーションコンテキスト全体を起動する必要があり、テストの実行が遅くなります。 これは、特に特定のWebサービスエンドポイントに対して高速で分離されたテストを作成する場合は特に望ましくないことがよくあります。

2.2. Spring Boot @WebServiceServerTest

Spring Boot 2.6は、@WebServiceServerTestアノテーションを使用してWebサービステストのサポートを拡張しました。

これは、アプリケーションコンテキスト全体をロードするのではなく、Webサービスレイヤーのみに焦点を当てたテストに使用できます。 つまり、必要な @Endpoint Beanのみを含むテストスライスを作成でき、@MockBeanを使用して依存関係をモックできます。

これは、 @ WebMvcTest @ DataJpaTest、などのSpring Bootによってすでに提供されている便利なテストスライスアノテーションと非常によく似ています。

3. サンプルプロジェクトの設定

3.1. 依存関係

Spring Boot Webサービスプロジェクトについてはすでに詳しく説明したので、ここでは、テストスコープの spring-ws-test依存関係を追加します。事業:

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-test</artifactId>
    <version>3.1.3</version>
    <scope>test</scope>
</dependency>

3.2. Webサービスの例

次に、指定した商品IDの商品データを返す簡単なサービスを作成しましょう。

@Endpoint
public class ProductEndpoint {

    @Autowired
    private ProductRepository productRepository;

    @ResponsePayload
    public GetProductResponse getProduct(@RequestPayload GetProductRequest request) {
        GetProductResponse response = new GetProductResponse();
        response.setProduct(productRepository.findProduct(request.getId()));
        return response;
    }
}

ここでは、 ProductEndpointコンポーネントに@Endpoint、の注釈を付けて、適切なXML要求を処理するために登録します。

getProduct メソッドは、要求オブジェクトを受け取り、応答を返す前にリポジトリから製品データを取得します。 ここでは、リポジトリの詳細は重要ではありません。 この場合、単純なメモリ内実装を使用して、アプリケーションを単純に保ち、テスト戦略に集中することができます。

4. エンドポイントテスト

最後に、テストスライスを作成し、WebサービスレイヤーでのXMLメッセージの正しい処理を確認できます。

@WebServiceServerTest
class ProductEndpointIntegrationTest {

    @Autowired
    private MockWebServiceClient client;

    @MockBean
    private ProductRepository productRepository;

    @Test
    void givenXmlRequest_whenServiceInvoked_thenValidResponse() throws IOException {
        Product product = createProduct();
        when(productRepository.findProduct("1")).thenReturn(product);

        StringSource request = new StringSource(
          "<bd:getProductRequest xmlns:bd='http://baeldung.com/spring-boot-web-service'>" + 
            "<bd:id>1</bd:id>" + 
          "</bd:getProductRequest>"
        );
        
        StringSource expectedResponse = new StringSource(
          "<bd:getProductResponse xmlns:bd='http://baeldung.com/spring-boot-web-service'>" + 
            "<bd:product>" + 
              "<bd:id>1</bd:id>" + 
              "<bd:name>Product 1</bd:name>" + 
            "</bd:product>" + 
          "</bd:getProductResponse>"
        );

        client.sendRequest(withPayload(request))
          .andExpect(noFault())
          .andExpect(validPayload(new ClassPathResource("webservice/products.xsd")))
          .andExpect(payload(expectedResponse))
          .andExpect(xpath("/bd:getProductResponse/bd:product[1]/bd:name", NAMESPACE_MAPPING)
            .evaluatesTo("Product 1"));
    }
}

ここでは、統合テストのアプリケーションで@Endpointのアノテーションが付けられたBeanのみを構成しました。 つまり、このテストスライスは、縮小されたアプリケーションコンテキストを作成します。 これにより、アプリケーションコンテキスト全体を繰り返しロードすることに伴うパフォーマンスの低下を招くことなく、ターゲットを絞った高速な統合テストを構築できます。

重要なことに、このアノテーションは、他の関連する自動構成とともにMockWebServiceClientも構成します。 その結果、このクライアントをテストに接続し、それを使用して getProductRequest XML要求を送信し、その後にさまざまな流暢な期待を送ることができます。

期待値は、応答XMLが特定のXSDスキーマに対して検証され、期待されるXML応答と一致することを確認します。 XPath式を使用して、応答XMLのさまざまな値を評価および比較することもできます。

4.1. エンドポイントコラボレーター

この例では、ProductEndpointで必要なリポジトリをモッキングするために@MockBeanを使用しました。 このモックがないと、完全な自動構成が無効になっているため、アプリケーションコンテキストを開始できません。 つまり、テストフレームワークは、テスト実行の前に@ Component、@ Service、または@RepositoryBeanを構成しません。

ただし、モックの代わりに実際の共同作業者が必要な場合は、@Importを使用してこれらを宣言できます。 Springはこれらのクラスを探し、必要に応じてエンドポイントに配線します。

4.2. コンテキスト全体の読み込み

前述のように、@WebServiceServerTestはアプリケーションコンテキスト全体をロードしません。 テストのためにアプリケーションコンテキスト全体をロードする必要がある場合は、 @SpringBootTest と組み合わせる @AutoConfigureMockWebServiceClient。 次に、前に示したように、このクライアントを同様の方法で使用して、要求を送信し、応答を検証できます。

5. 結論

この記事では、Spring Bootで導入された@WebServiceServerTestアノテーションについて説明しました。

最初に、WebサービスアプリケーションでのSpring Bootテストサポートについて話しました。 続いて、このアノテーションを使用してWebサービスレイヤーのテストスライスを作成する方法を確認しました。これは、高速で集中的な統合テストの構築に役立ちます。

いつものように、完全なソースコードはGitHubから入手できます。