0

私の Citrus テストでは、JSON ドキュメント (WireMock の出力) に埋め込まれた XML メッセージを検証しようとしています。無視したいタイムスタンプが含まれているため、XML テキストを解析する必要があります。JSON メッセージの XML 部分は次のようになります。

"requests": [
{
    "id": "52844d5a-59de-4288-8000-7f48fcda41e5",
    "request": {
        "body": "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"> [content omitted] </soapenv:Body></soapenv:Envelope>",
}
]

これは私のJavaテストコードです:

http()
    .client(wiremockClient)
    .receive()
    .response(HttpStatus.OK)
    .messageType(MessageType.JSON)
    .extractFromPayload("$.requests[0].request.body", "body")
    .payload(new ClassPathResource("output/esb/add_conf_to_cart/response2.xml"))
;

ここで、respon2.xml には XML テキスト (上記の JSON メッセージの「本文」の内容) のみが含まれ、Citrus から取得したエラーは次のとおりです。

com.consol.citrus.exceptions.CitrusRuntimeException: Failed to parse JSON text
…
Caused by: net.minidev.json.parser.ParseException: Unexpected token <soapenv:Envelope xmlns:soapenv=

では、JSON ドキュメントに埋め込まれた XML を検証するにはどうすればよいでしょうか?

4

3 に答える 3

1

明確化

現在のソリューションについて 2 つのコメントがあります。

  1. extractFromPayload(..)bodyJSONの一部を という名前の Citrus 変数に抽出しますbody。これはパートとは関係ありませんpayload(..)。の JSON コンテンツをbody Citrus 変数に保存しましたbody。あなたはこれに気づいているかもしれないし、気づいていないかもしれません

  2. このpayload(..)メソッドは、受信したペイロード全体、つまり JSON オブジェクト全体を常に検証します。

  3. 応答の一部のみを検証する場合は、JSON パス検証を使用します。 .validate("$.some.json.path", "someValue")

解決

Citrus は、ユース ケースに正確に対応する内部メソッドを提供します。matchsXml()のドキュメントを参照してください。

XML 構造のみを検証する

これが最も簡単な解決策です。

http()
    .client(wiremockClient)
    .receive()
    .response(HttpStatus.OK)
    .messageType(MessageType.JSON)
    .validate("$.requests[0].request.body", @matchesXml('citrus:readFile('classpath:output/esb/add_conf_to_cart/response2.xml')')@)

JSON レスポンス全体の検証

あなたの場合、JSON 構造全体を単純に一致させ、メソッド@matchesXml('<some><validation_xml></some></validation_xml>')@を正しい JSON エントリに配置します。

http()
.client(wiremockClient)
.receive()
.response(HttpStatus.OK)
.messageType(MessageType.JSON)
.payload("{\n"+
    "  \"requests\": {\n"+
    "    \"id\": \"52844d5a-59de-4288-8000-7f48fcda41e5\",\n"+
    "    \"request\": {\n"+
    "      \"body\": \"@matchesXml('<soapenv:Envelope xmlns:soapenv=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\"> [content omitted] </soapenv:Body></soapenv:Envelope>')@\"\n"+
    "    }\n"+
    "  }\n"+
    "}");

備考

  • に入れる文字列はpayload有効な JSON でなければなりません。つまり、JSON 値内の引用符はエスケープする必要があります。
  • Java String 内の引用符もエスケープする必要があるため、次のように記述する必要があります。\\\"
  • Citrus はpayload最初に文字列を JSON として解析し、エスケープされた引用符がエスケープされていない JSON オブジェクトとして内部的に保持します。次に、この文字列を検証関数に渡しますmatchesXml
  • </soapenv:Body>タグが開かれていないため、現在の例は有効な XML ではありません
  • ペイロード リクエストを個別のファイルに入れる方がはるかに簡単ですが、ファイルは有効な JSON でなければならないことに注意してください。\"
  • 別のファイルから XML コンテンツを読み取ることができます。この場合、Citrusのcitrus:readFile()関数を使用できます
  • の場合payload、XML 内の引用符をエスケープする必要があります。あなたはそうすることができますcitrus:translate()citrus:translate('citrus:readFile('classpath:some/path/to/response.xml')', '\"', '\\"')
  • Java、JSON、XML では特殊な引用符とバックスラッシュを扱っているため、エスケープは非常にトリッキーです。
  • 次のように動作するはずです。

ファイルを作成しますresponse_validation.json:

{
  "requests": {
    "id": "52844d5a-59de-4288-8000-7f48fcda41e5",
    "request": {
      "body": "@matchesXml('${jsonEscapedXmlInput}')@"
    }
  }
}

テスト ケースjsonEscapedXmlInputで、XML ファイルを読み取ってエスケープする Citrus 変数を作成します。

variable("jsonEscapedXml", "citrus:translate('citrus:readFile('classpath:output/esb/add_conf_to_cart/response2.xml')', '\\\"', '\\\\\"')")

それからそれを使用してください

http()
    .client(wiremockClient)
    .receive()
    .response(HttpStatus.OK)
    .messageType(MessageType.JSON)
    .payload(new ClassPathResource("classpath:validation/response_validation.json"))
;
于 2017-10-20T10:12:40.453 に答える