JavaFX与Junit

我想测试具有TextField或DatePicker之类的JavaFX场景元素的方法.我在这里找到了How do you unit test a JavaFX controller with JUnit如何运行JavaFX应用程序的测试,如果我只有一个初始化线程的测试类,它对我来说很好用.但是如果我有两节课怎么办?我无法使用启动方法初始化同一线程,因为将引发异常.如果我不会在第二个测试类中创建线程,那么还会有另一个异常.您可以在下面找到测试类和堆栈跟踪.我也在考虑使用@AfterClass批注在方法中停止该线程,然后在第二类中再次启动它,但是我认为这是不可能的.有人可以帮助我吗?

FirstTestClass

@RunWith(PowerMockRunner.class)
@PrepareForTest({TextField.class, DatePicker.class})
public class FirstTestClass {

    @BeforeClass
    public static void javaFXInitializer() throws SQLException, InterruptedException {
        Thread thread = new Thread("JavaFX Init Thread") {
            public void run() {
                Application.launch(Main.class);
            }
        };
        thread.setDaemon(true);
        thread.start();
        Thread.sleep(5000);
    }

    @Test
    public void firstTest() {
        TextField textFieldMock = mock(TextField.class);
        DatePicker datePickerMock = mock(DatePicker.class);
        TestClass objectUnderTest = new TestClass();

        when(textFieldMock.getText()).thenReturn("2000");
        when(datePickerMock.getValue()).thenReturn(LocalDate.of(1992,1,1));

        //rest of code to test
    }

}

SecondTestClass

@RunWith(PowerMockRunner.class)
    @PrepareForTest({TextField.class, DatePicker.class})
    public class SecondTestClass {

        @BeforeClass
        public static void javaFXInitializer() throws SQLException, InterruptedException {
            Thread thread = new Thread("JavaFX Init Thread") {
                public void run() {
                    Application.launch(Main.class);
                }
            };
            thread.setDaemon(true);
            thread.start();
            Thread.sleep(5000);
        }

        @Test
        public void firstTest() {
            TextField textFieldMock = mock(TextField.class);
            DatePicker datePickerMock = mock(DatePicker.class);
            TestClass objectUnderTest = new TestClass();

            when(textFieldMock.getText()).thenReturn("5000");
            when(datePickerMock.getValue()).thenReturn(LocalDate.of(1990,1,1));

            //rest of code to test
        }

    }

当我在两个类中初始化线程时发生异常

Exception in thread "JavaFX IncomeTest Init Thread" java.lang.RuntimeException: java.lang.UnsatisfiedLinkError: Native Library C:\Program Files\Java\jdk1.8.0_144\jre\bin\glass.dll already loaded in another classloader
        at com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:267)
        at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:211)
        at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:675)
        at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:695)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.UnsatisfiedLinkError: Native Library C:\Program Files\Java\jdk1.8.0_144\jre\bin\glass.dll already loaded in another classloader
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1907)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
        at java.lang.Runtime.load0(Runtime.java:809)
        at java.lang.System.load(System.java:1086)
        at com.sun.glass.utils.NativeLibLoader.loadLibraryFullPath(NativeLibLoader.java:201)
        at com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:94)
        at com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:39)
        at com.sun.glass.ui.Application.loadNativeLibrary(Application.java:112)
        at com.sun.glass.ui.Application.loadNativeLibrary(Application.java:120)
        at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
        at com.sun.glass.ui.win.WinApplication$1.run(WinApplication.java:118)
        at com.sun.glass.ui.win.WinApplication$1.run(WinApplication.java:91)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.glass.ui.win.WinApplication.<clinit>(WinApplication.java:91)
        at com.sun.glass.ui.win.WinPlatformFactory.createApplication(WinPlatformFactory.java:39)
        at com.sun.glass.ui.win.WinPlatformFactory.createApplication(WinPlatformFactory.java:36)
        at com.sun.glass.ui.Application.run(Application.java:146)
        at com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:257)
        ... 5 more

仅在第一类中初始化线程时发生异常

java.lang.ExceptionInInitializerError
        at sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:45)
        at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
        at org.mockito.internal.creation.instance.ObjenesisInstantiator.newInstance(ObjenesisInstantiator.java:14)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.createProxy(ClassImposterizer.java:149)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:64)
        at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMethodInvocationControl(DefaultMockCreator.java:121)
        at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMock(DefaultMockCreator.java:69)
        at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.mock(DefaultMockCreator.java:46)
        at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:141)
        at 
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:326)
        at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
        at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:310)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:298)
        at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
        at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:218)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:160)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:134)
        at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
        at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
        at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:136)
        at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)
        at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
        at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
        at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
        at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
        at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:550)
        at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:512)
        at javafx.scene.control.Control.<clinit>(Control.java:87)
        ... 50 more
最佳答案
创建一个类MockApp扩展Application并具有一个静态方法init().在该方法中,创建一个新的单线程,以适当的保护措施在其中调用JavaFX平台(基本上是您已经完成的工作).保护(布尔标志)保证该方法被调用一次max.关键是线程永远不会终止,从而使您可以在所有测试的生存期内访问JavaFX平台.要注意的是,您需要添加以下内容:

@BeforeClass
public void init() {
    MockApp.init();
}

对于每个使用JavaFX的测试类,因为您不知道测试的运行顺序.

在实践here中可以看到该方法(稍有更改).

转载注明原文:JavaFX与Junit - 代码日志