JUnit测试遇ExceptionInInitializerError:JavaFX Toolkit未初始化
问题:JUnit测试JavaFX相关代码时出现Toolkit未初始化异常
测试代码
@org.junit.jupiter.api.Test void createReservation() { modelManager.createReservation(new Reservation(new Item(1232,"title","author",2002,new MyDate(12,07,2021),"comment") { public String toString() { return null; } },"firstname","lastname","test@test.com",true,new MyDate(12,07,2023),new MyDate(24,07,2023))); Reservation reservation= modelManager.getReservations().get(0); assertEquals(new MyDate(),reservation.getStartDate()); }
报错信息
java.lang.ExceptionInInitializerError at javafx.controls/javafx.scene.control.DialogPane.createContentLabel(DialogPane.java:167) at javafx.controls/javafx.scene.control.DialogPane.<init>(DialogPane.java:218) at javafx.controls/javafx.scene.control.Dialog.<init>(Dialog.java:512) at javafx.controls/javafx.scene.control.Alert.<init>(Alert.java:247) at javafx.controls/javafx.scene.control.Alert.<init>(Alert.java:222) at FairyTaleLib/com.sep1re.fairytalelib.model.LibModelManager.<init>(LibModelManager.java:64) at FairyTaleLib/com.sep1re.fairytalelib.model.LibModelManagerTest.setUp(LibModelManagerTest.java:22) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) Caused by: java.lang.IllegalStateException: Toolkit not initialized
测试初始化代码
private ArrayList<Item> items; private LibModelManager modelManager; @org.junit.jupiter.api.BeforeEach void setUp() { items=new ArrayList(); modelManager= new LibModelManager(); }
问题根源
LibModelManager构造函数中创建了JavaFX的Alert组件,但JUnit测试环境默认不会初始化JavaFX Toolkit,从而引发Toolkit not initialized异常。
解决方案
方案1:分离UI与业务逻辑(推荐)
- 将创建Alert的UI代码从业务模型类
LibModelManager中抽离,移至专门的UI控制器类。 - 业务类仅处理核心业务逻辑,通过返回状态标识、触发事件或回调的方式,通知UI层处理弹窗展示。这样测试业务逻辑时完全不依赖JavaFX组件,从根源避免问题。
方案2:在测试中初始化JavaFX Toolkit
若暂时无法重构代码,可在测试类中添加初始化逻辑:
@BeforeAll static void initJavaFX() { // 创建JFXPanel会自动初始化JavaFX Toolkit new JFXPanel(); }
JFXPanel是JavaFX提供的跨组件嵌入类,实例化它会触发JavaFX Toolkit的初始化,后续创建Alert就不会报错。- 需将代码放在
@BeforeAll修饰的静态方法中,确保所有测试执行前完成初始化。
方案3:模拟Alert逻辑
如果无需测试Alert的展示效果,可通过Mockito模拟相关依赖:
- 重构
LibModelManager,将创建Alert的逻辑封装为独立服务类,并通过构造函数注入该服务。 - 测试时用Mockito创建该服务的模拟对象,替换真实的Alert创建逻辑,避免触发JavaFX相关代码。
内容的提问来源于stack exchange,提问作者Babovnik
相关产品推荐
相关产品推荐

