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

编写Arquillian测试Java Map Tuple方法时遇空值问题求助

Arquillian测试中Map元素获取返回null的排查与修复

问题背景

实现了regionMap方法,通过JPA查询CanadianPersonalIncomeTaxRate实体,将结果转换为以省份名称(provinceName)为键、省份缩写(provinceAbbreviation)为值的Map<String, String>,返回加拿大唯一省份的映射。编写Arquillian测试时,Map的大小验证通过,但通过get(0)、get(1)获取元素时返回null,无法得到预期的省份信息。

regionMap方法代码

// provinceName is key, provinceAbbreviation is value
public Map<String, String> regionMap() {
    return em.createQuery("""
        select distinct p.provinceName as prov_id, p.provinceAbbreviation as prov_value
        from CanadianPersonalIncomeTaxRate p
        order by p.provinceName """, Tuple.class)
            .getResultStream()
            .collect(Collectors.toMap(
                            tuple -> tuple.get(0, String.class),
                            tuple -> tuple.get(1, String.class)
                    )
            );
}

原测试代码

@Order(2)
@ParameterizedTest
@CsvSource({
        "13,Alberta,AB,Yukon,YT"
})
void regionMap(int expectedSize, String firstProvinceName, String firstProvinceAbbreviation,
               String lastProvinceName, String lastProvinceAbbreviation) {
    assertNotNull(_canadianPersonalIncomeTaxRateRepository);
    // Arrange
    Map<String, String> provinceList = _canadianPersonalIncomeTaxRateRepository.regionMap();
    // Assert
    assertEquals(expectedSize, provinceList.size());
    assertEquals(firstProvinceName, provinceList.get(0) );
    assertEquals(firstProvinceAbbreviation, provinceList.get(1) );
   // assertEquals(lastProvinceName, provinceList.get() );
   // assertEquals(lastProvinceAbbreviation, provinceList.get() );
}

错误原因

核心问题是混淆了Map与List的访问逻辑:

  • regionMap返回的Map<String, String>是以省份名称(如"Alberta")作为键的键值对集合,不是按索引顺序存储的List。
  • 测试中使用provinceList.get(0)、provinceList.get(1),是尝试用Integer类型的数字索引作为键去查找Map中的元素,但Map的键是String类型的省份名称,完全不匹配,因此返回null。

修复后的测试代码

将Map元素的获取方式改为以省份名称为键,对应断言省份缩写是否符合预期:

@Order(2)
@ParameterizedTest
@CsvSource({
        "13,Alberta,AB,Yukon,YT"
})
void regionMap(int expectedSize, String firstProvinceName, String firstProvinceAbbreviation,
               String lastProvinceName, String lastProvinceAbbreviation) {
    assertNotNull(_canadianPersonalIncomeTaxRateRepository);
    // Arrange
    // 变量名修正为更准确的provinceMap,避免误解为List
    Map<String, String> provinceMap = _canadianPersonalIncomeTaxRateRepository.regionMap();
    // Assert
    assertEquals(expectedSize, provinceMap.size());
    // 用省份名称作为键,获取对应的缩写并断言
    assertEquals(firstProvinceAbbreviation, provinceMap.get(firstProvinceName));
    // 验证最后一个省份的映射
    assertEquals(lastProvinceAbbreviation, provinceMap.get(lastProvinceName));
}

额外优化建议

  1. Tuple取值更安全:在regionMap方法中,建议使用查询语句中定义的别名(prov_id、prov_value)来获取Tuple值,避免因查询字段顺序调整导致的错误:
.collect(Collectors.toMap(
        tuple -> tuple.get("prov_id", String.class),
        tuple -> tuple.get("prov_value", String.class)
)
  1. 变量名规范:原测试中的provinceList变量名不符合实际类型,改为provinceMap更清晰,减少后续维护误解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:17:37