Java 当数据返回包含或不包含子项(填充或没有现有数组)的项时,如何验证PACT

Java 当数据返回包含或不包含子项(填充或没有现有数组)的项时,如何验证PACT,java,pact,Java,Pact,我使用PACT和Java进行合同测试,我的问题是我有一个api,其中的项目可能会出现如下情况: [ { "programCode": "ELA_NGL_G7_TX", "contentResources": [ { "tocPosition": 1827, "contentIdentifier": "l_6bf0783e-8499-4f6c-9f9b-c8fbdc8dcf6b_e5f25016-e2fa-4223-8969-2004c644917

我使用PACT和Java进行合同测试,我的问题是我有一个api,其中的项目可能会出现如下情况:

[
 {
  "programCode": "ELA_NGL_G7_TX",
  "contentResources": [
    {
        "tocPosition": 1827,
        "contentIdentifier": "l_6bf0783e-8499-4f6c-9f9b-c8fbdc8dcf6b_e5f25016-e2fa-4223-8969-2004c644917d"
    },
    {
        "tocPosition": 1828,
        "contentIdentifier": "l_192af774-54b9-4280-87e9-71f2b86a7d4d_e5f25016-e2fa-4223-8969-2004c644917d",
        "skills": [
            {
                "skillId": "ae836bd9-4758-4665-b3f8-8339313363e3",
                "spineId": "63c2b7d0-cd69-4e8a-9761-c90623104b8c"
            }
        ]
    }
]
所以正如你所看到的,有时候内在技能数组会出现,而其他的它不会,也不确定如何在我的消费者测试中加入这个场景。我的意思是,如果响应有或没有技能数组取决于特定的参数,我可以有两个不同的测试,这可能是好的,但这里它们来自同一个调用。所以我想我需要的是类似if-else的东西,如果技能数组存在,那么我会断言它的内部子元素,否则就忽略它

这是我的消费者:

@ExtendWith(PactConsumerTestExt.class)
public class PublishContractWithTocGetSummaryTest {

Map<String, String> headers = new HashMap<>();

String getRecommendations = "/toc/getsummary/ELA_NGL_G7_TX";

@Pact(provider = "CRS-METADATA-FILTERING-SERVICE", consumer = "CRS-TOC-RECOMMENDER")
public RequestResponsePact createPact(PactDslWithProvider builder) throws IOException {

    headers.put("Content-Type", "application/json");

    DslPart body = new PactDslJsonBody()
            .stringValue("programCode", "ELA_NGL_G7_TX")
            .eachLike("contentResources")
                .integerType("tocPosition", 0)
                .stringType("contentIdentifier", "l_9d23cb4f-69dc-4032-bb53-73501234dc14_e5f25016-e2fa-4223-8969-2004c644917d")
            .closeArray();

    return builder
            .given("get TOC Summary")
            .uponReceiving("get TOC Summary")
            .path(getRecommendations)
            .method("GET")
            .headers(headers)
            .willRespondWith()
            .status(200)
            .body(body)
            .toPact();
}

非常感谢。

对你的问题的简短回答是,没有一种方法可以完全满足你的需求

常见问题解答中提供了有关为什么不提供该选项的详细答案:

为什么不支持指定可选属性? 首先,假设您在进行验证测试时可以控制提供商的数据和消费者的数据。如果你不这样做,那么也许这个协定就是

其次,如果Pact支持断言响应中可能存在元素$.body.name,那么您可以编写消费者代码来处理可选的$.body.name,但事实上,提供者提供了$.body.firstname,任何测试都不会不告诉您做出了错误的假设。请记住,提供者可以在不违反合同的情况下返回额外数据,但它必须至少提供您期望的数据

指定某个_值或null也是如此。如果您的所有提供者验证测试数据都为此密钥返回null,您可能会认为您已经验证了SOME_值,但事实上,您从未验证过。在生产中,您可能会为该密钥获得完全不同的SOME_值,这可能会导致问题

指定长度为0或更大的数组也是如此。如果所有提供程序验证数据返回0长度数组,则所有验证测试都将通过,而您从未验证过数组的内容。这就是为什么只能指定最小长度为1的数组或长度为零的数组

请记住,与描述文档所有可能状态的模式不同,Pact是通过示例进行约定的。如果您需要断言多个变体是可能的,那么您需要为每个变体提供一个示例。但是,在你对每一个变化都做一个协定测试之前,想想它是否真的很重要。请记住,每个交互都有维护和执行时间的成本,并且您需要考虑在特定情况下是否值得花费。您最好先处理契约中的常见场景,然后将您的消费者写入代码,以优雅地处理意外变化,例如忽略该数据并发出警报


因此,TL;贝思博士的回答:

决定什么是有价值的测试-空数组、非空数组或两者兼而有之 使用提供者状态指定响应使用者测试的任何变化 实现提供者测试能够控制响应的状态