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

JUnit单元测试报expected:<null> but was错误咨询

JUnit单元测试报错排查与修复

报错信息

expected:<null> but was: expected:<null> but was:<Order ID: 1, Customer ID: 1, Customer Name: jordan harrison, Item ID: 1, Item Name: Call of Duty, Quantity: 0, Total Cost: 0.0>

核心根因

4个问题叠加导致测试不通过:

  • 断言参数顺序写反:JUnit的assertEquals()规则是第一个参数传预期值,第二个参数传被测方法返回的实际值,你的代码把DAO查询返回值放在了预期位,自己构造的对照对象放在了实际位,直接导致报错提示逻辑混乱,出现嵌套的expected提示。
  • DAO层查询逻辑不全:read()方法的SQL只关联了order_items和items两张表,没有关联订单主表、客户表,根本没有查询客户信息、购买数量、订单总金额这些字段;结果集映射方法orderItemsFromResultSet()也只给Order对象赋值了orderId和item属性,客户、数量、总金额全是默认值,和你构造的完整Order对象属性不一致。
  • 实体类缺少相等判断逻辑:Order、Item、Customer这些自定义实体类没有重写equals()和hashCode()方法,默认继承Object类的相等判断是对比对象内存地址,哪怕两个对象所有属性完全一致,不同new出来的实例也会被判定为不相等。
  • 结果集遍历缺少判空:read()方法里直接调用resultSet.next()没有判断返回值,如果查询不到对应数据会直接抛出SQLException,被catch捕获后返回null,也会触发断言失败。

单元测试通用排查方法

以后遇到同类断言报错按这个顺序查,效率最高:

  1. 先核对断言参数顺序,严格按照「预期值在前,实际值在后」的规则写,避免报错信息误导排查方向。
  2. 断言前分别打印预期对象、实际返回对象的全量属性,逐字段对比差异,不要只看断言的简略提示。
  3. 顺着被测方法的执行链路逐行走:先看入参是否正确,再看SQL/业务逻辑有没有漏处理分支,最后看结果映射有没有漏赋值字段。
  4. 自定义值对象必须按业务规则重写equals()和hashCode(),否则不要直接用assertEquals()做对象整体判断,可以拆成单个属性逐次断言。

具体修复步骤

  1. 修正测试类的断言顺序:
// 原错误写法
// assertEquals(DAO.read(order.getOrderId()), order);
// 修正后:第一个参数放自己构造的、符合预期的完整对象,第二个放DAO返回结果
assertEquals(order, DAO.read(order.getOrderId()));
  1. 补全DAO层查询与映射逻辑:
    • 修改read()方法的SQL,关联orders主表、customers表,把需要的客户ID、客户姓名、购买数量、订单总金额字段全部查出来
    • 重命名orderItemsFromResultSet()为更清晰的mapOrderFromResultSet(),在方法内把所有查询到的字段逐一set到Order对象中,包括关联的Customer实例、quantity、totalCost属性
    • 给resultSet.next()加判断,如果返回false说明没有查到对应数据,直接返回null,避免触发SQLException
  2. 给Order、Item、Customer三个实体类重写equals()和hashCode()方法,比如Order可以按orderId作为相等判断的核心依据,也可以根据业务需要对比全属性。如果暂时不想重写equals,可以把对象整体断言拆成单个属性断言,比如先断言orderId相等,再断言item属性相等,再断言customer属性相等,出问题能直接定位到哪个字段不匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 14:09:25