首页 > 解决方案 > Spring Cloud 合约测试无法正确解析 JSON

问题描述

我正在使用 Spring 云合同测试来尝试对 API 进行合同测试,但无法弄清楚是什么导致我的测试失败。

我正在使用这个 groovy 测试文件

package contracts.api.myClass;

import org.springframework.cloud.contract.spec.Contract

Contract.make {
  request {
    method 'GET'
    url value(consumer(regex('path/myAPI/(\\w+)')), producer('/path/myAPI/id'))
    headers {
      contentType(applicationJson())
    }
  }

  response {
    status 200
    headers {
      contentType(applicationJson())
    }
    body("""
      {
        "requestId": "id",
        "success": true,
        "datalist": [
          {
            "id": 100,
            "names": ["aaaa", "ffff"]
          }
        ],
        "failureInfo": {
          "failureCode": 100,
          "failureDesc": "failure"
        }
      }
    """)
  }
}

我尝试测试的 API 是使用来自以下 yaml 的 swagger code gen 2.0 生成的

'/configurator/myAPI/{requestId}':
    get:
      operationId: myAPI
      parameters:
        - $ref: '#/parameters/GCCX-Request-Context'
        - $ref: '#/parameters/GCCX-TransactionId'
        - $ref: '#/parameters/X-B3-TraceId'
        - $ref: '#/parameters/Accept-Language'
        - $ref: '#/parameters/requestId'
      tags:
        - Configurator
      consumes: [ ]
      responses:
        '200':
          description: Return the response once operation is preformed in BO.
          headers:
            Content-Language:
              description: Describes the natural language(s) of the intended audience for the enclosed entity. Note that this might not be equivalent to all the languages used within the entity-body.
              type: string
            GCCX-TransactionId:
              description: Id to trace the request for debugging purposes
              type: string
            X-B3-TraceId:
              description: Sleuth trace id used to trace multiple requests
              type: string
            X-B3-SpanId:
              description: Sleuth span id used for a single unit of work
              type: string
          schema:
            $ref: '#/definitions/MyDataResponse'
        '400':
          $ref: "#/responses/BadRequest"
        '401':
          $ref: "#/responses/Unauthorized"
        '403':
          $ref: "#/responses/Forbidden"
        '404':
          $ref: "#/responses/NotFound"
        '406':
          $ref: "#/responses/NotAcceptable"
        '415':
          $ref: "#/responses/UnsupportedMediaType"
        '429':
          $ref: "#/responses/TooManyRequests"
        '500':
          $ref: "#/responses/InternalServerError"
        '503':
          $ref: "#/responses/ServiceUnavailable"

MyDataResponse:
    type: object
    required:
      - requestId
      - success
      - datalist
      - failureInfo
    properties:
      requestId:
        type: string
      success:
        type: boolean
      datalist:
        type: array
        items:
          $ref: '#/definitions/DataEntry'
      failureInfo:
        $ref: "#/definitions/FailureInfo"
  DataEntry:
    type: object
    required:
      - names
      - id

groovy 测试自动生成到以下 java 测试中:

    @Test
    public void validate_myAPI() throws Exception {
        // given:
            MockMvcRequestSpecification request = given()
                    .header("Content-Type", "application/json");

        // when:
            ResponseOptions response = given().spec(request)
                    .get("path/myAPI/id");

        // then:
            assertThat(response.statusCode()).isEqualTo(200);
            assertThat(response.header("Content-Type")).matches("application/json.*");

        // and:
            DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
            assertThatJson(parsedJson).field("['requestId']").isEqualTo("id");
            assertThatJson(parsedJson).field("['success']").isEqualTo(true);
            assertThatJson(parsedJson).array("['dataList']").contains("['id']").isEqualTo(100);
            assertThatJson(parsedJson).array("['dataList']").array("['names']").arrayField().isEqualTo("aaaa").value();
            assertThatJson(parsedJson).array("['dataList']").array("['names']").arrayField().isEqualTo("ffff").value();
            assertThatJson(parsedJson).field("['failureInfo']").field("['failureCode']").isEqualTo(100);
            assertThatJson(parsedJson).field("['failureInfo']").field("['failureDesc']").isEqualTo("failure");

当我运行此测试时,尝试从数据列表中获取 id 字段时失败,但出现以下异常。

java.lang.RuntimeException: com.jayway.jsonpath.PathNotFoundException: Missing property in path $['datalist']

在调试模式下运行,我可以验证 parsedJson 确实具有 dataList 映射和其中包含的元素,但在测试期间无法找到它们。是否有人对可能导致问题的原因或我可以采取哪些步骤来调试问题有任何想法?根据公司政策,我已将所有用例特定类型/api 更改为通用版本(即 myAPI、dataList 等),因此任何大小写问题或命名差异都可能是由于我对代码的转录而不是任何问题。我所有的组件和功能测试都顺利通过,所以我相信这只是我如何设置合同测试文件的问题

标签: javaspringspring-cloudspring-cloud-contract

解决方案


推荐阅读