2013-08-25 6 views
17

Ich möchte grundlegende JUnit Test für JavaFX 8-Anwendung erstellen. Ich habe dieses einfache Code-Beispiel:Basic JUnit Test für JavaFX 8

public class Main extends Application { 
    public static void main(String[] args) { 
     Application.launch(args); 
    } 
    @Override 
    public void start(Stage primaryStage) { 
     primaryStage.setTitle("Tabs"); 
     Group root = new Group(); 
     Scene scene = new Scene(root, 400, 250, Color.WHITE); 
     TabPane tabPane = new TabPane(); 
     BorderPane borderPane = new BorderPane(); 
     for (int i = 0; i < 5; i++) { 
      Tab tab = new Tab(); 
      tab.setText("Tab" + i); 
      HBox hbox = new HBox(); 
      hbox.getChildren().add(new Label("Tab" + i)); 
      hbox.setAlignment(Pos.CENTER); 
      tab.setContent(hbox); 
      tabPane.getTabs().add(tab); 
     } 
     // bind to take available space 
     borderPane.prefHeightProperty().bind(scene.heightProperty()); 
     borderPane.prefWidthProperty().bind(scene.widthProperty()); 

     borderPane.setCenter(tabPane); 
     root.getChildren().add(borderPane); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 
} 

ich nur diesen Code habe bisher:

import javafx.application.Application; 
import javafx.stage.Stage; 
import org.junit.BeforeClass; 

public class BasicStart extends Application { 

    @BeforeClass 
    public static void initJFX() { 
     Thread t = new Thread("JavaFX Init Thread") { 
      @Override 
      public void run() { 
       Application.launch(BasicStart.class, new String[0]); 
      } 
     }; 
     t.setDaemon(true); 
     t.start(); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     // noop 
    } 
} 

Können Sie mir sagen, wie ich JUnit-Test für den obigen Code erstellen kann?

+2

Ich empfehle JemmyFX Verwendung würde - es braucht, um Setup ein wenig Zeit und Mühe und gewöhnen, aber es ist sehr mächtig. Wahrscheinlich werden Sie viel Zeit und Mühe darauf verwenden, etwas nicht so gut zu machen, wenn Sie von vorne anfangen. – assylias

Antwort

3

Der einfachste aproach ist folgende:

import javafx.application.Platform; 
import javafx.embed.swing.JFXPanel; 
import javafx.stage.Stage; 

import org.junit.Test; 

public class BasicStart { 

    @Test 
    public void testA() throws InterruptedException { 
     Thread thread = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       new JFXPanel(); // Initializes the JavaFx Platform 
       Platform.runLater(new Runnable() { 

        @Override 
        public void run() { 
         new Main().start(new Stage()); // Create and 
                 // initialize 
                 // your app. 

        } 
       }); 
      } 
     }); 
     thread.start();// Initialize the thread 
     Thread.sleep(10000); // Time to use the app, with out this, the thread 
           // will be killed before you can tell. 
    } 

} 

Hoffe, es hilft!

+6

Ich würde Thread.sleep() vermeiden, wenn Sie können. Es ist keine große Sache mit wenigen Tests, aber es wird wirklich langsamer, wenn Sie Hunderte von Tests haben. Sehen Sie, ob Sie stattdessen eine Art Latch verwenden können. –

+0

Wie es aussieht, scheint dies nicht eine fehlgeschlagene Assertion (innerhalb 'run') zu melden, die die normalen JUnit-Berichtmechanismen verwendet, weil' Runnable' keine 'Exception' propagieren kann. –

26

Ich verwende eine Junit-Regel, um Komponententests auf dem JavaFX-Thread auszuführen. Die Details sind in this post. Kopieren Sie einfach die Klasse aus diesem Post und fügen Sie dann dieses Feld zu Ihren Komponententests hinzu.

@Rule public JavaFXThreadingRule javafxRule = new JavaFXThreadingRule(); 

Dieser Code funktioniert sowohl für JavaFX 2 und JavaFX 8.

+1

Das funktioniert ganz gut, aber das Ausführen des Tests auf dem Thread bedeutet, dass Sie keine Betten oder Wartezeiten haben können und Code, der platform.runLater verwendet, kann nicht getestet werden - es sei denn, Sie können eine Arbeit vorschlagen? – Adam

+0

@Adam Warum können Sie keine Betten oder Wartezeiten verwenden? Sie werden im Allgemeinen nicht in Komponententests empfohlen, aber ich sehe nicht, warum Sie sie nicht verwenden könnten, wenn Sie wirklich gebraucht würden. Wenn Sie Platform.runLater() verwenden möchten, können Sie einfach auf dem Hauptthread ausführen, andernfalls warum müssen Sie Platform.runLater() aufrufen, wenn Sie bereits auf dem javafx-Thread sind? –

+1

Um es besser zu erklären ... Ich spreche hier von Integrationstests, nicht wirklich Unit Tests, obwohl ich JUnit verwende. Wenn die Anzeige von einem anderen Thread aktualisiert wird, sagen Sie einen Netzwerkclient, dann Platform.runLater (runnable) muss verwendet werden, jedoch wird Runnable erst ausgeführt, nachdem der Test (ausgeführt auf dem fx-Thread) abgeschlossen wurde und die Steuerung an die Hauptkomponente zurückgegeben hat FX-Thread, der dann den nächsten Job in der Warteschlange bearbeitet. – Adam

2

Basierend auf Brian Blonski ‚s answer Ich habe eine JUnit-Testrunner, die im Wesentlichen die gleiche Sache tut, ist aber ein bisschen einfacher meiner Meinung nach verwenden, . Mit ihm würde Ihr Test wie folgt aussehen:

@RunWith(JfxTestRunner.class) 
public class MyUnitTest 
{ 
    @Test 
    public void testMyMethod() 
    { 
    //... 
    } 
} 
+1

Es scheint, dass dein Link gebrochen ist. Ich hätte gerne den TestRunner gesehen! – MikaelF

+1

Ich habe den Link repariert. Aber ich sollte dich warnen; Ich fand den Code nicht threadsicher. –