我有一个在 maven 下演示 JavaFX + TestFX 的小项目。我用:
- Java(TM) SE 运行时环境 (build 1.8.0_40-b26)
- 阿帕奇 Maven 3.2.5 (12a6b3acb947671f09b81f49094c53f426d8cea1; 2014-12-14T21:29:23+04:00)
完整来源:https ://github.com/alevohin/testfx-maven-example
我有 2 个无法解决的问题:
1) 当我从 IDE (IDEA) 启动 AppFXTest 时,测试失败
java.lang.ClassNotFoundException: com.sun.glass.ui.monocle.MonoclePlatformFactory
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.sun.glass.ui.PlatformFactory.getPlatformFactory(PlatformFactory.java:42)
at com.sun.glass.ui.Application.run(Application.java:146)
at com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:263)
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$152(LauncherImpl.java:182)
at com.sun.javafx.application.LauncherImpl$$Lambda$4/367732825.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Failed to load Glass factory class
如果我禁用 Monocle,它会起作用。但我看到了真正的 JavaFX 窗口和真正的光标单击按钮(“非无头”模式)
2)当我尝试通过 maven 执行测试(evecute mvn clean test)时,我得到另一个错误
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project testfx-maven-example: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test failed: java.lang.NoClassDefFoundError: javafx/stage/Stage: javafx.stage.Stage -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project testfx-maven-example: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test failed: java.lang.NoClassDefFoundError: javafx/stage/Stage
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:224)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:355)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:155)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:584)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:216)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:160)
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:497)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
...
Caused by: java.lang.ClassNotFoundException: javafx.stage.Stage
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.apache.maven.surefire.booter.IsolatedClassLoader.loadClass(IsolatedClassLoader.java:97)
... 48 more
我的 pom.xml 看起来像
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alevohin</groupId>
<artifactId>testfx-maven-example</artifactId>
<version>1.0-SNAPSHOT</version>
<url>https://github.com/alevohin/javafx-maven-example</url>
<dependencies>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testfx</groupId>
<artifactId>testfx-core</artifactId>
<version>4.0.1-alpha</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testfx</groupId>
<artifactId>testfx-junit</artifactId>
<version>4.0.1-alpha</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jfxtras</groupId>
<artifactId>openjfx-monocle</artifactId>
<version>1.8.0_20</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<threadCount>1</threadCount>
<systemPropertyVariables>
<glass.platform>Monocle</glass.platform>
<monocle.platform>Headless</monocle.platform>
<prism.order>sw</prism.order>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
AppFXTest
public final class AppFXTest extends ApplicationTest {
@Override
public void start(final Stage stage) throws Exception {
new AppFX().start(stage);
}
@Test
public void showsButtons() throws Exception {
MatcherAssert.assertThat(
lookup(".button").queryAll().size(),
Matchers.is(2)
);
}
@Test
public void showsBottom() throws Exception {
final Label label = lookup("BOTTOM").queryFirst();
MatcherAssert.assertThat(
label.isVisible(),
Matchers.is(true)
);
}
@Test
public void clicksButtons() throws Exception {
clickOn("A").clickOn("B");
}
}
应用程序
public final class AppFX extends Application {
/**
* Program entry point.
* @param args Program arguments.
*/
public static void main(final String... args) {
Application.launch(AppFX.class, args);
}
@Override
public void start(final Stage stage) throws Exception {
stage.setTitle("TEST");
final Scene scene = new Scene(this.centralPane());
scene.getStylesheets().add(
AppFX.class.getResource("App.css").toExternalForm()
);
stage.setScene(scene);
stage.setMinWidth(800.0D);
stage.setMinHeight(600.0D);
stage.show();
}
private Pane centralPane() {
final BorderPane border = new BorderPane();
border.setTop(this.buttonsPane());
border.setCenter(this.centerPane());
border.setBottom(this.bottomPane());
return border;
}
private Pane buttonsPane() {
final HBox controls = new HBox();
controls.setSpacing(5.0D);
controls.setAlignment(Pos.BASELINE_CENTER);
controls.getChildren().add(new Label("BUTTONS"));
controls.getChildren().add(new Button("A"));
controls.getChildren().add(new Button("B"));
return controls;
}
private Pane centerPane() {
final VBox pane = new VBox();
pane.setAlignment(Pos.CENTER);
pane.getChildren().add(new Label("CENTER"));
pane.setMinSize(600.0D, 400.0D);
return pane;
}
private Pane bottomPane() {
final VBox bottom = new VBox();
final HBox status = new HBox();
status.setAlignment(Pos.BASELINE_RIGHT);
bottom.getChildren().add(status);
status.getChildren().add(new Label("BOTTOM"));
return bottom;
}
}
更新
有问题
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project testfx-maven-example: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test failed: java.lang.NoClassDefFoundError: javafx/stage/Stage: javafx.stage.Stage -> [Help 1]
通过additionalClasspathElements
像这样添加到 pom.xml 来解决
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
...
<additionalClasspathElements>
<additionalClasspathElement>${java.home}/lib/ext/jfxrt.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>