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

Spring Boot中如何测试REST接口返回整数或浮点数?

解决JSON数值类型匹配问题:同时兼容整数与浮点数

你遇到的问题其实很典型:JSON里的数值类型在解析时会保留原始类型(整数是Integer,浮点数是Double),而Hamcrest的is()匹配器会做严格的equals比较——比如Integer(17)和BigDecimal(17)或者Double(17.0)调用equals()都会返回false,导致测试失败。

下面给你两种简单有效的解决方案:

方案一:使用closeTo匹配器(适合浮点数场景)

如果你的数值精度要求不高,可以用closeTo匹配器,它会忽略类型差异,只比较数值是否在指定误差范围内(这里误差设为0就相当于精确匹配)。

修改后的测试代码:

import static org.hamcrest.Matchers.closeTo;
// 其他静态导入不变

@ParameterizedTest
@MethodSource("createTestData")
void testNumbersEndpoint(final String restServiceValue, final double expectedValue) throws Exception {
    given(restTemplate.getForObject(any(String.class), eq(String.class))).willReturn(restServiceValue);
    mockMvc.perform(get("/number"))
            .andExpect(status().isOk())
            // 使用closeTo替代is,误差设为0.0
            .andExpect(jsonPath("number", closeTo(expectedValue, 0.0)));
}

private static Stream<Arguments> createTestData() {
    return Stream.of(
            Arguments.of("17", 17.0),
            Arguments.of("12.53", 12.53)
    );
}

这个方案的好处是不需要改动测试数据的类型,直接复用你原来的double类型预期值即可。

方案二:使用comparesEqualTo匹配器(适合高精度场景)

如果你的业务对数值精度要求很高(比如涉及金额计算),推荐用BigDecimal结合comparesEqualTo匹配器——它会调用compareTo方法做数值比较,只要数值相等就会匹配,不管原始类型是Integer还是Double。

修改后的测试代码:

import static org.hamcrest.Matchers.comparesEqualTo;
import java.math.BigDecimal;
// 其他静态导入不变

@ParameterizedTest
@MethodSource("createTestData")
void testNumbersEndpoint(final String restServiceValue, final BigDecimal expectedValue) throws Exception {
    given(restTemplate.getForObject(any(String.class), eq(String.class))).willReturn(restServiceValue);
    mockMvc.perform(get("/number"))
            .andExpect(status().isOk())
            // 使用comparesEqualTo匹配BigDecimal数值
            .andExpect(jsonPath("number", comparesEqualTo(expectedValue)));
}

private static Stream<Arguments> createTestData() {
    return Stream.of(
            // 注意用字符串构造BigDecimal避免精度丢失
            Arguments.of("17", new BigDecimal("17")),
            Arguments.of("12.53", new BigDecimal("12.53"))
    );
}

这里要注意用字符串构造BigDecimal,避免直接用double值带来的精度问题(比如new BigDecimal(0.1)其实是一个近似值)。

为什么你之前的尝试无效?

你之前用Number和BigDecimal结合is()匹配器时,is()本质是调用equals()方法,而Integer和BigDecimal的equals()不仅比较数值,还会比较类型,所以Integer(17).equals(new BigDecimal(17))会返回false,导致测试失败。而上面的两种方案都是基于数值比较而非对象相等性比较,所以能兼容不同的数值类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:22:43