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

JUnit测试在代码存在人为植入错误时仍全部通过的问题排查

JUnit sell方法测试恒通过问题排查

你的测试无论业务代码是否出错都能通过,核心原因是你从始至终都没有调用被测的sell方法,整个测试逻辑是你在测试方法里重写了一遍自己理解的业务流程,完全没有校验实际业务方法的执行结果,本质是在"自导自演",自然永远不会失败。

具体问题点

  • 未调用被测业务方法
    整个reStock测试方法中没有任何一行调用sell(myUser, item)的代码。所有角色校验、库存遍历、商品匹配、余额判断的逻辑都是你在测试代码里手写复刻的,和你业务类中实现的sell方法完全无关。哪怕你把sell方法的代码全部删掉改成空实现,测试依然会按照你自己写的分支逻辑执行,不会检测到任何问题。
  • 断言全部是无意义的自校验
    你写的所有断言都是对自己测试代码中刚生成的判断结果做校验,永远不会失败:
    • 你先通过if(myUser.getRole() == Roles.CASHIER)进入分支,再断言myUser.getRole() == Roles.CASHIER,属于恒真判断
    • 你自己在测试代码里执行inventories.remove(inventory),再断言集合长度变化,本质是在测试JDK中ArrayList的remove功能,和你的业务逻辑没有任何关系
    • 所有错误分支(非收银员角色、商品不匹配、余额不足)里只有打印语句,没有任何失败断言,哪怕走到错误场景,测试也只会打一行日志就正常标记为通过
  • 缺少明确的测试前置初始化
    测试依赖的myUser、inventories、item等成员变量没有固定的初始化逻辑,状态完全不确定,很容易出现所有断言分支都没走到,测试空跑通过的情况。

正确测试写法参考

写JUnit测试的固定流程是:初始化测试场景 -> 调用被测方法 -> 断言方法执行后的实际结果符合预期,不要在测试里重写业务逻辑。

// 每个测试执行前先构造固定的测试数据,避免状态干扰
@BeforeEach
void setUp() {
    inventories = new ArrayList<>();
    // 往库存里加一个售价100的商品apple
    inventories.add(new Product("apple", 100));
    // 构造余额200的收银员用户
    myUser = new User(Roles.CASHIER, 200);
}

@Test
void sell_shouldRemoveItem_whenCashierHasEnoughBalance() {
    int sizeBeforeSell = inventories.size();
    // 核心:调用被测的sell方法
    sell(myUser, "apple");
    // 断言执行结果符合预期
    Assertions.assertEquals(sizeBeforeSell - 1, inventories.size());
    boolean appleStillInStock = inventories.stream()
            .anyMatch(p -> "apple".equals(p.getName()));
    Assertions.assertFalse(appleStillInStock);
}

@Test
void sell_shouldKeepStock_whenUserIsNotCashier() {
    User normalStaff = new User(Roles.STAFF, 200);
    int sizeBeforeSell = inventories.size();
    sell(normalStaff, "apple");
    // 非收银员购买,库存不应该变化
    Assertions.assertEquals(sizeBeforeSell, inventories.size());
}

@Test
void sell_shouldKeepStock_whenCashierBalanceNotEnough() {
    User poorCashier = new User(Roles.CASHIER, 50);
    int sizeBeforeSell = inventories.size();
    sell(poorCashier, "apple");
    // 余额不足,库存不应该变化
    Assertions.assertEquals(sizeBeforeSell, inventories.size());
}

补充说明:你当前实现的sell方法本身也存在逻辑问题,比如遍历ArrayList时直接调用remove会抛出ConcurrentModificationException,再比如遍历库存时只要遇到不匹配的商品就打印"缺货",哪怕库存中实际存在目标商品。等你把测试逻辑写正确之后,这些问题都会在跑测试时被自动检测出来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:24:27