如何为Main类的静态main方法及menuForBill方法编写单元测试
单元测试问题求助
我是单元测试新手,想要为Main类中的方法编写单元测试,但遇到了三个问题:
- 不知道如何处理main方法的
String[] args参数; - 无法直接调用
Main.menuForBill静态方法; - 单元测试代码编译报错:
error: Class names, 'a', are only accepted if annotation processing is explicitly requested
以下是相关代码及报错信息,求解决方法:
Main类代码
public static void menuForBill(Bill bill, Menu menu) throws IOException { Scanner scanner = new Scanner(System.in); String option="0"; BillServices billServices = new BillServicesImpl(); BillFileHandlingServices billFileHandlingServices = new BillFileHandlingServicesImpl(); BillPrinter billPrinter = new BillPrinterImpl(); while (!option.equals("e")){ System.out.println("\nBill management"); System.out.println("1. Create Bill "); System.out.println("2. Update Bill "); System.out.println("3. Delete Bill"); System.out.println("4. Show Bill"); System.out.println("5. Export bill"); System.out.println("6. Import bill"); System.out.println("e. To escape"); System.out.print("\nChoose your option:"); option = scanner.next(); switch (option){ case "1" -> billServices.addBill(bill,menu); case "2" -> billServices.updateBill(bill,menu); case "3" -> billServices.deleteBillItems(bill); case "4" -> {try { billPrinter.printBill(bill); }catch (NullPointerException exception){ System.out.println(exception.getMessage()); }} case "5" -> billFileHandlingServices.exportBill(bill); case "6" -> billFileHandlingServices.importBill(); case "e" -> {} default -> System.out.println("Not found for your option !!!"); } } } public static void main(String[] args) throws IOException { Scanner scanner = new Scanner(System.in); String option; Menu menu = new Menu(); Bill bill = new Bill(); while (true){ System.out.println("\n1.Menu management"); System.out.println("2.Bill management"); System.out.print("Please choose which types Management you want to work with:"); option = scanner.next(); switch (option){ case "1" -> menuForOrder(menu); case "2" -> menuForBill(bill,menu); default -> System.out.println("Out of option !!!"); } } }
单元测试代码
public class MainTest { private final InputStream systemIn = System.in; private final PrintStream systemOut = System.out; private ByteArrayInputStream testIn; private ByteArrayOutputStream testOut; @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); @Before public void init(){ testOut = new ByteArrayOutputStream(); System.setOut(new PrintStream(testOut)); } @After public void restoreSystemInputOutput(){ System.setIn(systemIn); System.setOut(systemOut); } @Test public void whenChoosingMenuManagement_returnMenuManagement() throws Exception { System.out.println("main"); systemInMock.provideLines("1"); Main.main(new String[]{"a"}); assertTrue(true); } }
报错信息
error: Class names, 'a', are only accepted if annotation processing is explicitly requested 1 error
解决方法
1. 编译报错修复
这个报错是编译命令使用错误导致的:你可能误将Main.main的参数当成了要编译的类名(比如用了javac MainTest.java a这类命令)。
正确操作:
- 先编译所有相关类:
javac *.java - 运行JUnit测试时,确保把JUnit相关jar包加入类路径:
java -cp .:junit.jar:hamcrest-core.jar org.junit.runner.JUnitCore MainTest - 若用IDEA/Eclipse等IDE,检查运行配置,不要把main方法的参数放到编译参数栏里。
2. main方法的String[] args参数处理
args是程序启动时的命令行参数,单元测试里可以自由传入测试用的数组:
- 不需要参数时传空数组:
Main.main(new String[0]) - 需要测试参数时传指定数组:
Main.main(new String[]{"testArg"})
你的代码里传new String[]{"a"}本身没问题,问题出在编译运行方式上。
3. 调用Main.menuForBill静态方法的问题
如果无法直接调用,排查以下几点:
- 确认
Main类是public修饰,且menuForBill方法为public static(从代码看符合要求); - 测试类若和
Main不在同包,需添加导入语句:import 你的包名.Main;; - 确保
Bill和Menu类已正确编译,测试方法中可直接创建实例调用:Bill testBill = new Bill(); Menu testMenu = new Menu(); Main.menuForBill(testBill, testMenu);
另外,注意main方法里的while(true)死循环会导致测试无法正常结束,建议重构代码将循环逻辑与业务逻辑分离,或者在测试中添加中断逻辑(比如模拟输入特定值退出循环)。
内容的提问来源于stack exchange,提问作者David Moore
相关产品推荐
相关产品推荐

