Wim*_*uwe 6 java javafx spring-test spring-boot testfx
我正在使用带有 JavaFX 的 Spring Boot 进行测试(基于一些解释这一点的优秀 YouTube 视频)。
为了使它与TestFX 一起工作,我需要创建这样的上下文:
@Override
public void init() throws Exception {
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyJavaFXApplication.class);
builder.headless(false); // Needed for TestFX
context = builder.run(getParameters().getRaw().stream().toArray(String[]::new));
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
loader.setControllerFactory(context::getBean);
rootNode = loader.load();
}
Run Code Online (Sandbox Code Playgroud)
我现在想测试这个 JavaFX 应用程序,为此我使用:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class MyJavaFXApplicationUITest extends TestFXBase {
@MockBean
private MachineService machineService;
@Test
public void test() throws InterruptedException {
WaitForAsyncUtils.waitForFxEvents();
verifyThat("#statusText", (Text text ) -> text.getText().equals("Machine stopped"));
clickOn("#startMachineButton");
verifyThat("#startMachineButton", Node::isDisabled);
verifyThat("#statusText", (Text text ) -> text.getText().equals("Machine started"));
}
}
Run Code Online (Sandbox Code Playgroud)
这将启动一个 Spring 上下文,并按预期用模拟 bean 替换“普通”bean。
但是,我现在得到了一个,java.awt.HeadlessException因为这个“无头”属性没有像正常启动期间那样设置为 false。如何在测试期间设置此属性?
编辑:
仔细观察,似乎有 2 个上下文已启动,一个是 Spring 测试框架启动的,另一个是我在init方法中手动创建的,因此被测应用程序未使用模拟 bean。如果有人知道如何在init()方法中获取测试上下文引用,我会很高兴。
小智 9
所述@SpringBootTest用途SpringBootContextLoader类作为上下文加载,所以在ApplicationContext是从方法负载SpringBootContextLoader.loadContext为这样:
SpringApplication application = getSpringApplication();
......
return application.run();
Run Code Online (Sandbox Code Playgroud)
调用该方法时application.run(),应用程序使用其内部无头属性配置系统无头属性。
因此,如果我们想在 Spring Boot 测试中设置 'headless' 属性,只需创建一个自定义的特定 ContextLoader 类扩展 SpringBootContextLoader 类,并getSpringApplication使用 set the headless 属性为 false覆盖该方法,然后为特定的 ContextLoader 分配注解@ContextConfiguration for @SpringBootTest。编码:
public class HeadlessSpringBootContextLoader extends SpringBootContextLoader {
@Override
protected SpringApplication getSpringApplication() {
SpringApplication application = super.getSpringApplication();
application.setHeadless(false);
return application;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=SpringBootTest.WebEnvironment.NONE)
@ContextConfiguration(loader = HeadlessSpringBootContextLoader.class)
public class ApplicationTests {
@Test
public void contextLoads() {
}
}
Run Code Online (Sandbox Code Playgroud)
Praveen Kumar 的评论指出了好的方向。当我使用 运行测试时-Djava.awt.headless=false,没有任何异常。
为了解决 2 个 Spring 上下文的其他问题,我必须执行以下操作:
假设这是您的主要 JavaFx 启动类:
@SpringBootApplication
public class MyJavaFXClientApplication extends Application {
private ConfigurableApplicationContext context;
private Parent rootNode;
@Override
public void init() throws Exception {
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyJavaFXClientApplication.class);
builder.headless(false); // Needed for TestFX
context = builder.run(getParameters().getRaw().stream().toArray(String[]::new));
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
loader.setControllerFactory(context::getBean);
rootNode = loader.load();
}
@Override
public void start(Stage primaryStage) throws Exception {
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
double width = visualBounds.getWidth();
double height = visualBounds.getHeight();
primaryStage.setScene(new Scene(rootNode, width, height));
primaryStage.centerOnScreen();
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void stop() throws Exception {
context.close();
}
public void setContext(ConfigurableApplicationContext context) {
this.context = context;
}
}
Run Code Online (Sandbox Code Playgroud)
为了进行测试,您使用这个抽象基类(由MVP Java提供的 YouTube 视频提供):
public abstract class TestFXBase extends ApplicationTest {
@BeforeClass
public static void setupHeadlessMode() {
if (Boolean.getBoolean("headless")) {
System.setProperty("testfx.robot", "glass");
System.setProperty("testfx.headless", "true");
System.setProperty("prism.order", "sw");
System.setProperty("prism.text", "t2k");
System.setProperty("java.awt.headless", "true");
}
}
@After
public void afterEachTest() throws TimeoutException {
FxToolkit.hideStage();
release(new KeyCode[0]);
release(new MouseButton[0]);
}
@SuppressWarnings("unchecked")
public <T extends Node> T find(String query, Class<T> clazz) {
return (T) lookup(query).queryAll().iterator().next();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以编写这样的测试:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class MyJavaFXApplicationUITest extends TestFXBase {
@MockBean
private TemperatureService temperatureService;
@Autowired
private ConfigurableApplicationContext context;
@Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
loader.setControllerFactory(context::getBean);
Parent rootNode = loader.load();
stage.setScene(new Scene(rootNode, 800, 600));
stage.centerOnScreen();
stage.show();
}
@Test
public void testTemperatureReading() throws InterruptedException {
when(temperatureService.getCurrentTemperature()).thenReturn(new Temperature(25.0));
WaitForAsyncUtils.waitForFxEvents();
assertThat(find("#temperatureText", Text.class).getText()).isEqualTo("25.00 C");
}
}
Run Code Online (Sandbox Code Playgroud)
这允许使用模拟服务启动 UI。
| 归档时间: |
|
| 查看次数: |
2888 次 |
| 最近记录: |