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

使用Hamcrest Contains Matcher时遭遇类型匹配失败问题求助

解决JSON返回值类型不匹配导致的验证失败问题

嘿,这个类型不匹配的坑我之前踩过,给你几个靠谱的解决思路:

1. 转换服务返回的JSON数据类型,对齐数据库的String类型

既然你的数据库返回的是String数组,那最好让服务返回的JSON数据也统一成字符串类型。如果是用JSON解析库(比如Jackson、Gson)处理返回结果,可以这么做:

  • 自定义反序列化逻辑:比如用Jackson的话,在对应字段上添加反序列化注解,把数字自动转成字符串:
    @JsonDeserialize(using = IntegerToStringDeserializer.class)
    private List<String> targetField;
    
    或者自己写个简单的转换逻辑,拿到反序列化后的Integer数组后,遍历转成String:
    List<Integer> actualIntList = // 从服务返回的JSON解析得到的列表
    List<String> actualStringList = actualIntList.stream()
                                                .map(String::valueOf)
                                                .collect(Collectors.toList());
    
    之后用这个actualStringList去和你的期望列表{"1", "1", ...}做contains匹配。

2. 调整Matcher的期望类型,适配服务返回的Integer类型

如果业务上允许服务返回数字类型,那可以直接修改你的测试期望,把字符串换成整数。比如原来的验证代码是:

assertThat(actualList, contains("1", "1", "1", "1", "1"));

改成:

assertThat(actualList, contains(1, 1, 1, 1, 1));

不过要注意,这个方案得确认是否符合业务逻辑——毕竟数据库返回的是String,服务返回数字可能是个小bug,最好先确认下服务端是否应该返回字符串类型。

3. 自定义Matcher兼容两种类型的匹配

如果有时候服务可能返回字符串,有时候返回数字,想让测试更灵活,可以自定义一个Hamcrest Matcher,自动处理类型转换:

public class StringOrIntegerMatcher extends TypeSafeMatcher<Object> {
    private final String expectedValue;

    public StringOrIntegerMatcher(String expectedValue) {
        this.expectedValue = expectedValue;
    }

    @Override
    protected boolean matchesSafely(Object item) {
        if (item instanceof String) {
            return expectedValue.equals(item);
        } else if (item instanceof Integer) {
            return expectedValue.equals(item.toString());
        }
        return false;
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("a string or integer equal to ").appendValue(expectedValue);
    }

    public static Matcher<Object> equalToAsStringOrInteger(String expected) {
        return new StringOrIntegerMatcher(expected);
    }
}

然后验证的时候就可以用这个自定义Matcher:

assertThat(actualList, contains(
    equalToAsStringOrInteger("1"),
    equalToAsStringOrInteger("1"),
    equalToAsStringOrInteger("1"),
    equalToAsStringOrInteger("1"),
    equalToAsStringOrInteger("1")
));

问题根源补充

你遇到的错误本质是JSON的类型特性:没有引号的数字会被解析成Integer类型,而你的数据库返回的是String数组,两边类型不一致,contains matcher默认是严格的类型+值匹配,所以就失败啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:55:24