2013-08-25 14 views
17

Desidero creare un test JUnit di base per l'applicazione JavaFX 8. Ho questo semplice esempio di codice:Test JUnit di base per 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(); 
    } 
} 

ho solo questo codice finora:

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 
    } 
} 

Potete dirmi come posso creare test JUnit per il codice di cui sopra?

+2

mi consiglia di utilizzare JemmyFX - ci vuole un po 'di tempo e fatica per l'installazione e abituarsi, ma è molto potente. Probabilmente impiegherete molto tempo e sforzi per fare qualcosa di meno buono se si ricomincia da zero. – assylias

risposta

3

L'aproach più semplice è la seguente:

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. 
    } 

} 

Speranza che aiuta!

+6

Eviterei Thread.sleep() se puoi. Non è un grosso problema con pochi test, ma rallenta davvero quando hai centinaia di test. Vedi se è possibile utilizzare una sorta di latch, invece. –

+0

Allo stato attuale questo non sembra riportare un'affermazione fallita (all'interno di 'run') usando i normali meccanismi di reporting JUnit, perché' Runnable' non può propagare un 'Exception'. –

26

Uso una regola Junit per eseguire test di unità sul thread JavaFX. I dettagli sono in this post. Basta copiare la classe da quel post e quindi aggiungere questo campo ai test di unità.

@Rule public JavaFXThreadingRule javafxRule = new JavaFXThreadingRule(); 

Questo codice funziona sia per JavaFX 2 e JavaFX 8.

+1

Funziona abbastanza bene, tuttavia, eseguire il test sul thread significa che non è possibile dormire o attendere e qualsiasi codice che utilizza platform.runLater non può essere testato, a meno che non si possa suggerire un lavoro in giro? – Adam

+0

@Adam Perché non si è in grado di utilizzare alcun sonno o attesa? In genere non è raccomandato l'uso nei test unitari, ma non vedo perché non potresti usarli se hai davvero bisogno. Se si desidera utilizzare Platform.runLater(), è possibile eseguire semplicemente il thread principale, altrimenti perché è necessario chiamare Platform.runLater() se si è già nel thread javafx? –

+1

Per cercare di spiegare meglio .... Sto parlando di test di integrazione qui, non proprio test di unità anche se si usa JUnit. Se il display viene aggiornato da un altro thread, ad esempio un client di rete, è necessario utilizzare Platform.runLater (eseguibile), tuttavia il runnable non viene eseguito fino a quando il test (in esecuzione sul thread fx) non ha completato e restituito il controllo al main Thread FX che servirà quindi il prossimo lavoro in coda. – Adam

2

Sulla base Brian Blonski s' answer ho creato un JUnit-Testrunner, che fa essenzialmente la stessa cosa, ma è un po' più semplice da usare, a mio parere . Con esso, il test sarebbe simile a questa:

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

Sembra che il tuo link sia rotto. Mi sarebbe piaciuto vedere il TestRunner! – MikaelF

+1

Ho risolto il collegamento. Ma dovrei avvertirti; Ho trovato il codice non protetto da thread. –