停止 JUnit 完成,直到所有其他线程都已停止
Stop JUnit from finishing until all other threads have been stopped
在单元测试期间,我想使用 Java FX 绘制一些图形。现在的问题是,一旦单元测试完成,JVM 和 Java FX 就会关闭,我无法检查生成的图(不像 "test" 只是从 main 方法开始)。所以我的问题是,有没有办法在特定线程完成之前阻止 JUnit 退出,即直接从 main 方法开始测试时复制行为?是的,我知道绘图很可能不是一般在单元测试期间应该完成的事情。
目前我正在做这样的事情:
//@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();
}
}
}
}
}
}
问题就在这里,我想摆脱这个讨厌的块,等待所有 JavaFX 平台明确退出。
我很欣赏关于使用倒计时锁存器而不是明确加入 Java FX 线程的答案。然而,这仍然需要我明确停止当前线程。但是,我宁愿 "tell" JUnit 以某种方式等待 JavaFX 线程完成。
所以基本上我正在寻找的是一种告诉 JUnit 等待特定线程的方法,而我的测试方法中没有任何阻塞代码。
附录:对于最小 运行 示例 类 是必要的
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();
}
为此使用 CountDownLatch
。
- 用
1
初始化。
- 当
Stage
关闭时,调用 countDown()
.
- 在 JUnit 测试中,调用
await()
等待 Stage
关闭。
示例:
CountDownLatch cdl = new CountDownLatch(1);
// TODO show the stage and do not forget to add cdl.countDown() to your
// stage.setOnCloseRequest
cdl.await();
备选方案 #1:
使用 JavaFX Junit Rule 直接在 FX 应用程序线程上执行所有操作。
备选方案 #2:
使用TestFX,就我从你更新的描述中读到的内容而言,它最适合。
在单元测试期间,我想使用 Java FX 绘制一些图形。现在的问题是,一旦单元测试完成,JVM 和 Java FX 就会关闭,我无法检查生成的图(不像 "test" 只是从 main 方法开始)。所以我的问题是,有没有办法在特定线程完成之前阻止 JUnit 退出,即直接从 main 方法开始测试时复制行为?是的,我知道绘图很可能不是一般在单元测试期间应该完成的事情。 目前我正在做这样的事情:
//@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();
}
}
}
}
}
}
问题就在这里,我想摆脱这个讨厌的块,等待所有 JavaFX 平台明确退出。 我很欣赏关于使用倒计时锁存器而不是明确加入 Java FX 线程的答案。然而,这仍然需要我明确停止当前线程。但是,我宁愿 "tell" JUnit 以某种方式等待 JavaFX 线程完成。
所以基本上我正在寻找的是一种告诉 JUnit 等待特定线程的方法,而我的测试方法中没有任何阻塞代码。
附录:对于最小 运行 示例 类 是必要的
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();
}
为此使用 CountDownLatch
。
- 用
1
初始化。 - 当
Stage
关闭时,调用countDown()
. - 在 JUnit 测试中,调用
await()
等待Stage
关闭。
示例:
CountDownLatch cdl = new CountDownLatch(1);
// TODO show the stage and do not forget to add cdl.countDown() to your
// stage.setOnCloseRequest
cdl.await();
备选方案 #1:
使用 JavaFX Junit Rule 直接在 FX 应用程序线程上执行所有操作。
备选方案 #2:
使用TestFX,就我从你更新的描述中读到的内容而言,它最适合。