如何 运行 在使用 JavaFX 元素的 Travis 上进行测试?
How to run a test on Travis which uses JavaFX elements?
我想测试一个方法(也在 Travis 上远程),它需要一个 JavaFX 元素作为参数,例如 ProgressIndicator
。
但是当我在我的测试方法中创建一个 new ProgressIndicator()
时,当我执行测试(使用 Gradle)时,它在该行上以
失败
ExceptionInInitializerError
(...)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
Question: How do I instantiate JavaFX elements in tests both locally and on Travis?
我已经检查过没有 ProgressIndicator 的测试是否通过。
相关信息
- Toolkit not initialized Java FX 澄清在 launch() 中启动 FX Toolkit 之前尝试创建 FX 控件会产生此错误,但我无法从中找到解决方案。我应该以某种方式从我的测试中调用 launch() 吗?
- JavaFX 2.1: Toolkit not initialized 似乎包含我的错误,但与 CI 的测试无关。一种解决方案涉及
CountDownLatch
,另一种类似地涉及将 com.sun.javafx.application.PlatformImpl.startup(()->{});
添加到您的测试中,但这只能解决本地问题并将生成 java.lang.UnsupportedOperationException
.
我的测试:
import javafx.scene.control.ProgressIndicator;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests {@link HelloJavaFX} class.
*/
class HelloJavaFXTest {
/**
* Test passes.
*/
@Test
public void testCalculate(){
HelloJavaFX helloJavaFX = new HelloJavaFX();
assertEquals(2, helloJavaFX.calculate(), "message");
}
/**
* Fails on `new ProgressIndicator();` line.
*/
@Test
public void testProgress() {
HelloJavaFX helloJavaFX = new HelloJavaFX();
ProgressIndicator progressIndicator = new ProgressIndicator();
assertTrue(helloJavaFX.setLoading(progressIndicator));
}
}
我的 JavaFX class:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Spinner;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* Sample class to show JavaFX.
*/
public class HelloJavaFX extends Application {
/** height */
public final int height = 250;
/** width */
public final int width = 300;
/**
* Main method.
* @param args Default
*/
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 1+1");
btn.setOnAction(event -> System.out.println(calculate()));
Spinner spinner = new Spinner();
StackPane root = new StackPane();
root.getChildren().add(btn);
root.getChildren().add(spinner);
primaryStage.setScene(new Scene(root, width, height));
primaryStage.show();
}
/**
* Show 1+1.
* @return 1+1
*/
public int calculate() {
return 1+1;
}
/**
* Indicate something is loading.
*
* @param progressIndicator User wants feedback.
*
* @return Whether the progress was succesfully set.
*/
public boolean setLoading(ProgressIndicator progressIndicator) {
progressIndicator.setVisible(true);
return true;
}
}
不确定是否相关,但我将 Gradle 与构建文件一起使用:
plugins {
id 'java'
}
description = """
Gradle build file.
This uses the gradle wrapper, so when running (the first time) use 'gradlew test' so then it
downloads the right gradle automatically.
"""
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.0.3'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.0.3'
}
sourceSets {
main.java.srcDirs += 'src'
main.resources.srcDirs += 'src'
test.java.srcDirs += 'test'
test.resources.srcDirs += 'test'
}
// Java target version
sourceCompatibility = 1.8
test {
// Enable JUnit 5 (Gradle 4.6+).
useJUnitPlatform()
// Always run tests, even when nothing changed.
dependsOn 'cleanTest'
// Show test results.
testLogging {
events "passed", "skipped", "failed"
}
}
堆栈跟踪:
java.lang.ExceptionInInitializerError
at deltadak.HelloJavaFXTest.testProgress(HelloJavaFXTest.java:26)
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.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:389)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod(TestMethodTestDescriptor.java:167)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:163)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:110)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute(HierarchicalTestExecutor.java:83)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$null(HierarchicalTestExecutor.java:92)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute(HierarchicalTestExecutor.java:92)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$null(HierarchicalTestExecutor.java:92)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute(HierarchicalTestExecutor.java:92)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:51)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:94)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access0(JUnitPlatformTestClassProcessor.java:80)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:71)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy1.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:123)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)
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)
完整示例回购是 here。
告诉我发生了什么。
如您所见,仅启动 JavaFX 只会在本地运行,因为 Travis 无法访问所有 JavaFX 元素!
你需要使用一个特殊的JavaFX测试库,例如TestFX. They have a 'getting started' on their wiki,它能做的更多,甚至可以模拟用户交互。
给我解答!
要将它与 Junit 5 一起使用,请将其添加到 gradle 构建中的 dependencies
块:
testCompile "org.testfx:testfx-core:4.0.12-alpha"
testCompile "org.testfx:testfx-junit:4.0.12-alpha"
关于你的测试,对于你真正简单的情况,它足以替换
class HelloJavaFXTest {
和
class HelloJavaFXTest extends FxRobot {
并替换
public void testProgress() {
和
public void testProgress() throws TimeoutException {
// Setup JavaFX for testing.
FxToolkit.registerPrimaryStage();
FxToolkit.setupApplication(HelloJavaFX.class);
其中 HelloJavaFX
应该是您的主要 class:扩展 Application
的那个。
不过,您确实需要更新 .travis.yml
,否则您会遇到 UnsupportedOperationException
。再次改编自他们的维基:
language: java
jdk: openjdk8
services:
- xvfb
before_install:
- sudo apt update
- sudo apt install openjfx
- chmod +x ./gradlew
- export DISPLAY=:99.0
install: true
script:
- ./gradlew check
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
- rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.bin
- rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.lock
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
科特林!
请注意,您甚至可以在 Kotlin 中使用它,例如使用 Spek 框架时!预告片:
object HelloJavaFXTest: Spek({
given("the JavaFX Toolkit") {
// Initialise JavaFX Toolkit, needed for things like ProgressIndicator.
FxToolkit.registerPrimaryStage()
FxToolkit.setupApplication(HelloJavaFX::class.java)
on("instantiating a JavaFX component") {
val progress = ProgressIndicator()
it("should not throw any errors") {
progress.isVisible = false
}
}
}
})
完整示例项目here。
我想测试一个方法(也在 Travis 上远程),它需要一个 JavaFX 元素作为参数,例如 ProgressIndicator
。
但是当我在我的测试方法中创建一个 new ProgressIndicator()
时,当我执行测试(使用 Gradle)时,它在该行上以
ExceptionInInitializerError
(...)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
Question: How do I instantiate JavaFX elements in tests both locally and on Travis?
我已经检查过没有 ProgressIndicator 的测试是否通过。
相关信息
- Toolkit not initialized Java FX 澄清在 launch() 中启动 FX Toolkit 之前尝试创建 FX 控件会产生此错误,但我无法从中找到解决方案。我应该以某种方式从我的测试中调用 launch() 吗?
- JavaFX 2.1: Toolkit not initialized 似乎包含我的错误,但与 CI 的测试无关。一种解决方案涉及
CountDownLatch
,另一种类似地涉及将com.sun.javafx.application.PlatformImpl.startup(()->{});
添加到您的测试中,但这只能解决本地问题并将生成java.lang.UnsupportedOperationException
.
我的测试:
import javafx.scene.control.ProgressIndicator;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests {@link HelloJavaFX} class.
*/
class HelloJavaFXTest {
/**
* Test passes.
*/
@Test
public void testCalculate(){
HelloJavaFX helloJavaFX = new HelloJavaFX();
assertEquals(2, helloJavaFX.calculate(), "message");
}
/**
* Fails on `new ProgressIndicator();` line.
*/
@Test
public void testProgress() {
HelloJavaFX helloJavaFX = new HelloJavaFX();
ProgressIndicator progressIndicator = new ProgressIndicator();
assertTrue(helloJavaFX.setLoading(progressIndicator));
}
}
我的 JavaFX class:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Spinner;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* Sample class to show JavaFX.
*/
public class HelloJavaFX extends Application {
/** height */
public final int height = 250;
/** width */
public final int width = 300;
/**
* Main method.
* @param args Default
*/
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 1+1");
btn.setOnAction(event -> System.out.println(calculate()));
Spinner spinner = new Spinner();
StackPane root = new StackPane();
root.getChildren().add(btn);
root.getChildren().add(spinner);
primaryStage.setScene(new Scene(root, width, height));
primaryStage.show();
}
/**
* Show 1+1.
* @return 1+1
*/
public int calculate() {
return 1+1;
}
/**
* Indicate something is loading.
*
* @param progressIndicator User wants feedback.
*
* @return Whether the progress was succesfully set.
*/
public boolean setLoading(ProgressIndicator progressIndicator) {
progressIndicator.setVisible(true);
return true;
}
}
不确定是否相关,但我将 Gradle 与构建文件一起使用:
plugins {
id 'java'
}
description = """
Gradle build file.
This uses the gradle wrapper, so when running (the first time) use 'gradlew test' so then it
downloads the right gradle automatically.
"""
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.0.3'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.0.3'
}
sourceSets {
main.java.srcDirs += 'src'
main.resources.srcDirs += 'src'
test.java.srcDirs += 'test'
test.resources.srcDirs += 'test'
}
// Java target version
sourceCompatibility = 1.8
test {
// Enable JUnit 5 (Gradle 4.6+).
useJUnitPlatform()
// Always run tests, even when nothing changed.
dependsOn 'cleanTest'
// Show test results.
testLogging {
events "passed", "skipped", "failed"
}
}
堆栈跟踪:
java.lang.ExceptionInInitializerError
at deltadak.HelloJavaFXTest.testProgress(HelloJavaFXTest.java:26)
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.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:389)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod(TestMethodTestDescriptor.java:167)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:163)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:110)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute(HierarchicalTestExecutor.java:83)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$null(HierarchicalTestExecutor.java:92)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute(HierarchicalTestExecutor.java:92)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$null(HierarchicalTestExecutor.java:92)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute(HierarchicalTestExecutor.java:92)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:51)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:94)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access0(JUnitPlatformTestClassProcessor.java:80)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:71)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy1.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:123)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)
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)
完整示例回购是 here。
告诉我发生了什么。
如您所见,仅启动 JavaFX 只会在本地运行,因为 Travis 无法访问所有 JavaFX 元素!
你需要使用一个特殊的JavaFX测试库,例如TestFX. They have a 'getting started' on their wiki,它能做的更多,甚至可以模拟用户交互。
给我解答!
要将它与 Junit 5 一起使用,请将其添加到 gradle 构建中的 dependencies
块:
testCompile "org.testfx:testfx-core:4.0.12-alpha"
testCompile "org.testfx:testfx-junit:4.0.12-alpha"
关于你的测试,对于你真正简单的情况,它足以替换
class HelloJavaFXTest {
和
class HelloJavaFXTest extends FxRobot {
并替换
public void testProgress() {
和
public void testProgress() throws TimeoutException {
// Setup JavaFX for testing.
FxToolkit.registerPrimaryStage();
FxToolkit.setupApplication(HelloJavaFX.class);
其中 HelloJavaFX
应该是您的主要 class:扩展 Application
的那个。
不过,您确实需要更新 .travis.yml
,否则您会遇到 UnsupportedOperationException
。再次改编自他们的维基:
language: java
jdk: openjdk8
services:
- xvfb
before_install:
- sudo apt update
- sudo apt install openjfx
- chmod +x ./gradlew
- export DISPLAY=:99.0
install: true
script:
- ./gradlew check
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
- rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.bin
- rm -f $HOME/.gradle/caches/*/fileHashes/fileHashes.lock
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
科特林!
请注意,您甚至可以在 Kotlin 中使用它,例如使用 Spek 框架时!预告片:
object HelloJavaFXTest: Spek({
given("the JavaFX Toolkit") {
// Initialise JavaFX Toolkit, needed for things like ProgressIndicator.
FxToolkit.registerPrimaryStage()
FxToolkit.setupApplication(HelloJavaFX::class.java)
on("instantiating a JavaFX component") {
val progress = ProgressIndicator()
it("should not throw any errors") {
progress.isVisible = false
}
}
}
})
完整示例项目here。