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,也会触发断言失败。
单元测试通用排查方法
以后遇到同类断言报错按这个顺序查,效率最高:
- 先核对断言参数顺序,严格按照「预期值在前,实际值在后」的规则写,避免报错信息误导排查方向。
- 断言前分别打印预期对象、实际返回对象的全量属性,逐字段对比差异,不要只看断言的简略提示。
- 顺着被测方法的执行链路逐行走:先看入参是否正确,再看SQL/业务逻辑有没有漏处理分支,最后看结果映射有没有漏赋值字段。
- 自定义值对象必须按业务规则重写
equals()和hashCode(),否则不要直接用assertEquals()做对象整体判断,可以拆成单个属性逐次断言。
具体修复步骤
- 修正测试类的断言顺序:
// 原错误写法 // assertEquals(DAO.read(order.getOrderId()), order); // 修正后:第一个参数放自己构造的、符合预期的完整对象,第二个放DAO返回结果 assertEquals(order, DAO.read(order.getOrderId()));
- 补全DAO层查询与映射逻辑:
- 修改
read()方法的SQL,关联orders主表、customers表,把需要的客户ID、客户姓名、购买数量、订单总金额字段全部查出来 - 重命名
orderItemsFromResultSet()为更清晰的mapOrderFromResultSet(),在方法内把所有查询到的字段逐一set到Order对象中,包括关联的Customer实例、quantity、totalCost属性 - 给
resultSet.next()加判断,如果返回false说明没有查到对应数据,直接返回null,避免触发SQLException
- 修改
- 给Order、Item、Customer三个实体类重写
equals()和hashCode()方法,比如Order可以按orderId作为相等判断的核心依据,也可以根据业务需要对比全属性。如果暂时不想重写equals,可以把对象整体断言拆成单个属性断言,比如先断言orderId相等,再断言item属性相等,再断言customer属性相等,出问题能直接定位到哪个字段不匹配。
内容的提问来源于stack exchange,提问作者AceKokuren
相关产品推荐
相关产品推荐

