You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pact JVM(JUnit5)如何定义正则匹配的无根数组响应?

问题描述

我正在使用JUnit5进行Pact JVM消费者契约测试,引入的Maven依赖如下:

<dependency>
  <groupId>au.com.dius.pact.consumer</groupId>
  <artifactId>junit5</artifactId>
  <scope>test</scope>
</dependency>

需要针对如下无根JSON数组响应创建DslPart匹配模式:

[
   "Africa/Abidjan",
   "Asia/Tokyo",
   "Africa/Addis_Ababa",
   ...
] 

目前定义了包含固定字符串元素的DslPart,消费者测试可通过:

DslPart expectedZoneResponse = new PactDslJsonArray()
        .stringValue("Africa/Abidjan")
        .stringValue("Asia/Tokyo");

Pact契约定义如下:

@Pact(consumer = "Client", provider = "ServiceApi")
public RequestResponsePact getTestArray(PactDslWithProvider builder) {
    return builder
           .given("ZoneInfo")
            .uponReceiving("Return all zones.")
              .path("/zones")
              .method("GET")
            .willRespondWith()
              .status(200)
              .body(expectedZoneResponse)
            .toPact();
}

但运行提供者契约测试时失败,报错:

body: $ Expected a List with 2 elements but received 603 elements

希望将DslPart改为使用正则表达式[a-zA-Z]+/[a-zA-Z]+匹配数组元素,而非固定字符串,同时解决数组元素数量不匹配的问题。

解决方案

要解决这个问题,需要同时实现两个目标:

  • 用正则表达式匹配数组中每个元素的格式
  • 允许数组包含任意数量(或至少指定数量)的元素

修改DslPart定义

使用PactDslJsonArray的minArrayLike或arrayLike方法定义数组的匹配规则,同时用stringMatcher指定元素的正则匹配模板:

DslPart expectedZoneResponse = new PactDslJsonArray()
        // 匹配至少1个符合规则的元素,可根据业务需求调整min值
        .minArrayLike(1, new PactDslJsonRootValue()
                // 第一个参数是正则表达式,第二个是示例值(用于消费者测试生成模拟响应)
                .stringMatcher("[a-zA-Z]+/[a-zA-Z_]+", "Africa/Abidjan"));

代码解释

  1. minArrayLike(min, value):指定数组至少包含min个元素,且每个元素都符合value定义的匹配规则。如果业务允许空数组,可改用arrayLike()。
  2. stringMatcher(regex, example):定义字符串元素的匹配规则,第一个参数是正则表达式,第二个是示例值。注意原正则[a-zA-Z]+/[a-zA-Z]+无法匹配带下划线的时区(如Africa/Addis_Ababa),所以调整为[a-zA-Z]+/[a-zA-Z_]+以覆盖所有场景。

修改后的完整契约代码

@Pact(consumer = "Client", provider = "ServiceApi")
public RequestResponsePact getTestArray(PactDslWithProvider builder) {
    DslPart expectedZoneResponse = new PactDslJsonArray()
            .minArrayLike(1, new PactDslJsonRootValue()
                    .stringMatcher("[a-zA-Z]+/[a-zA-Z_]+", "Africa/Abidjan"));

    return builder
           .given("ZoneInfo")
            .uponReceiving("Return all zones.")
              .path("/zones")
              .method("GET")
            .willRespondWith()
              .status(200)
              .body(expectedZoneResponse)
            .toPact();
}

这样修改后,提供者测试时会验证返回的数组中每个元素都符合正则格式,且元素数量不少于1个,不会再因为元素数量不匹配而报错。

内容的提问来源于stack exchange,提问作者MMR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:53:30