Stop JUnit before all other threads finish

During my unit tests, I would like to draw some numbers using Java FX. Now the problem is that as soon as the Unit test is finished, the JVM and therefore Java FX will shut down and I will not be able to test the generated graphs (unlike the case when the "test" just starts from the main method). So my question is if there is a way to stop JUnit from exiting before specific threads have finished, i.e. To reproduce the behavior as the test is run from the main method directly? And yes, I know that conspiracy is probably not something that needs to be done during the Unit test in general. At the moment I am doing something like this:

//@ContextConfiguration(classes = {DummyConfig.class }) 
//@RunWith(SpringJUnit4ClassRunner.class)
public class MainViewTest {

    private boolean fromMain = false;

    // starting the "test" from main does not require explicit waiting for 
    // for the JavaFX thread to finish .. I'd like to replicate this
    // behaviour in JUnit (by configuring JUnit, not my test or application code)
    public static void main(String [] args){
        new MainViewTest(true).test();
    }

    public MainViewTest(){}

    private MainViewTest(boolean fromMain){
        this.fromMain = fromMain;
    }

    @Test
    public void test() {

        //do some tests....

        //plot some results...
        PlotStage.plotStage(new QPMApplication() {
            @Override
            public Stage createStage() {
                Stage stage = new Stage();
                StackPane root = new StackPane();
                Scene scene = new Scene(root, 300, 300);
                stage.setTitle("Stage");
                stage.setScene(scene);
                stage.setOnCloseRequest(new EventHandler<WindowEvent>(){
                    @Override
                    public void handle(WindowEvent event) {
                        Platform.exit();
                    }
                 });
                return stage;
            }
        });

        System.out.println("Stage started");
        // how to get rid of this block (or using a countdownlatch) but
        // still waiting for the threads to finish?
        Set<Thread> threads = Thread.getAllStackTraces().keySet();
        if (!fromMain) {
            System.out.println("checking threads...");
            for (Thread thread : threads) {
                if (thread.getName().contains("JavaFX")) {
                    try {
                        thread.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

      

The problem here is that I want to get rid of this nasty block so I can wait for the entire JavaFX platform to be explicitly removed. I appreciate the answer related to using a countdown shutter instead of explicitly attaching to the Java FX stream. However, this still requires me to explicitly stop the current thread. However, I'd rather "tell" JUnit to somehow wait for the JavaFX thread to finish.

So basically what I'm looking for is a way to tell JUnit to wait for specific threads without any blocking code inside my test methods.

Appendix: Required Classes for a Minimal Working Example

public class PlotStage {

    public static boolean toolkitInialized = false;

    public static void plotStage(QPMApplication stageCreator) {
        if (!toolkitInialized) {
            Thread appThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    Application.launch(InitApp.class);
                }
            });
            appThread.start();
        }

        while (!toolkitInialized) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                Stage stage = stageCreator.createStage();
                stage.show();
            }
        });
    }

    public static class InitApp extends Application {
        @Override
        public void start(final Stage primaryStage) {
            toolkitInialized = true;
        }
    }
}


public interface QPMApplication {
   public abstract  Stage createStage();
}

      

+3


source to share


1 answer


Use CountDownLatch

for this.

  • Initialize with 1

    .
  • When Stage

    closed, call countDown()

    .
  • In JUnit test, call await()

    to wait for close Stage

    .

Example:

CountDownLatch cdl = new CountDownLatch(1);
// TODO show the stage and do not forget to add cdl.countDown() to your
//   stage.setOnCloseRequest
cdl.await();

      




Alternative # 1:

Use JavaFX Junit Rule to perform all actions directly in your FX application.




Alternative # 2:

Use TestFX , for which I read from your updated description, it fits the best.

+1


source







All Articles