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

如何使用Junit测试CoffeeMaker控制台程序的用户输入输出逻辑

咖啡机程序JUnit输入输出测试解决方案

错误原因说明

  • 空指针异常:Main类中的coffeeMaker是静态私有成员,你在测试类中实例化的CoffeeMaker对象和Main类持有的静态实例无关,直接调用Main.mainMenu()时Main的静态coffeeMaker未完成初始化,调用其方法就会触发空指针。
  • 栈溢出错误:Main类所有操作执行完成后都会递归调用mainMenu()形成死循环,你仅传入了一个"5"的输入,输入流读取完毕后后续读取操作会持续报错,触发无限递归调用mainMenu(),最终栈溢出。

解决方案

你需要做以下调整:

  1. 测试前后备份原始的System.in和System.out,测试完成后立即恢复,避免污染其他测试用例
  2. 输入内容需要包含两条指令:先输入5查询库存,再输入0退出程序,避免无限递归
  3. 捕获System.exit(0)调用,避免测试进程被直接终止
  4. 直接调用Main.main()方法触发初始化,无需自己在测试类中实例化CoffeeMaker
  5. 输出匹配时可以选择校验整体输出包含库存内容,避免额外打印信息影响匹配结果

修改后的测试代码示例

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import java.io.*;
import java.security.Permission;

public class CoffeeMakerTest {
    private InputStream originalIn;
    private PrintStream originalOut;
    private SecurityManager originalSecurityManager;
    private int exitCode;

    @Before
    public void setUp() {
        // 备份原始的输入输出和安全管理器
        originalIn = System.in;
        originalOut = System.out;
        originalSecurityManager = System.getSecurityManager();
        // 自定义安全管理器捕获System.exit请求
        System.setSecurityManager(new SecurityManager() {
            @Override
            public void checkExit(int status) {
                exitCode = status;
                throw new SecurityException("Prevent System.exit from terminating test");
            }
            @Override
            public void checkPermission(Permission perm) {}
        });
    }

    @After
    public void tearDown() {
        // 恢复原始配置
        System.setIn(originalIn);
        System.setOut(originalOut);
        System.setSecurityManager(originalSecurityManager);
    }

    @Test
    public void testCheckInventoryOption() {
        String lineSeparator = System.getProperty("line.separator");
        // 构造输入:先输入5,再输入0退出
        String input = "5" + lineSeparator + "0" + lineSeparator;
        System.setIn(new ByteArrayInputStream(input.getBytes()));

        ByteArrayOutputStream testOut = new ByteArrayOutputStream();
        System.setOut(new PrintStream(testOut));

        // 调用main方法,会自动初始化Main的静态coffeeMaker
        try {
            Main.main(new String[]{});
        } catch (SecurityException ignored) {
            // 捕获退出抛出的异常,不影响测试
        }

        // 构造期望的库存输出
        String expectedInventory = "Coffee: 15" + lineSeparator
                + "Milk: 15" + lineSeparator
                + "Sugar: 15" + lineSeparator
                + "Chocolate: 15" + lineSeparator;

        // 验证输出中包含期望的库存内容
        assertTrue(testOut.toString().contains(expectedInventory));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:09:04