如何在Spring Boot测试中设置'headless'属性? [英] How to set 'headless' property in a Spring Boot test?

查看:432
本文介绍了如何在Spring Boot测试中设置'headless'属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试使用Spring Boot with JavaFX(基于一些优秀的YouTube视频,解释这个)。



使其适用于 TestFX ,我需要创建这样的上下文:

  @Override 
public void init()throws Exception {
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyJavaFXApplication.class);
builder.headless(false); //需要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();
}

我现在想测试这个JavaFX应用程序,为此我使用:

  @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class MyJavaFXApplicationUITest扩展了TestFXBase {

@MockBean
private MachineService machineService;

@Test
public void test()抛出InterruptedException {
WaitForAsyncUtils.waitForFxEvents();
verifyThat(#statusText,(文本文本) - > text.getText()。equals(Machine stopped));
clickOn(#startMachineButton);
verifyThat(#startMachineButton,Node :: isDisabled);
verifyThat(#statusText,(文本文本) - > text.getText()。equals(Machine started));
}
}

这将启动Spring上下文并替换normal与预期的模拟豆豆。



但是,我现在得到一个 java.awt.HeadlessException ,因为这个'headless'属性没有设置为false就像在正常启动期间完成一样。如何在测试期间设置此属性?



编辑:



仔细观察似乎有2上下文启动,一个是Spring测试框架启动的,另一个是我在 init 方法中手动创建的,因此测试中的应用程序不使用模拟bean。如果有人想知道如何在 init()方法中获取测试上下文引用,我会非常高兴。

解决方案

Praveen Kumar的评论指出了良好的方向。当我用 -Djava.awt.headless = false 运行测试时,没有例外。



To解决2 Spring上下文的另一个问题,我必须执行以下操作:



假设这是您的主JavaFx启动类:

  @SpringBootApplication 
公共类MyJavaFXClientApplication扩展Application {

private ConfigurableApplicationContext context;
private父rootNode;

@Override
public void init()抛出异常{
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyJavaFXClientApplication.class);
builder.headless(false); //需要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()抛出异常{
context.close();
}

public void setContext(ConfigurableApplicationContext context){
this.context = context;
}
}

对于测试,您使用此抽象基类( 通过 MVP Java提供此YouTube视频 ):

 公共抽象类TestFXBase扩展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()抛出TimeoutException {
FxToolkit.hideStage();
release(new KeyCode [0]);
release(new MouseButton [0]);
}

@SuppressWarnings(未选中)
public< T extends Node> T find(String query,Class< T> clazz){
return(T)lookup(query).queryAll()。iterator()。next();
}
}

然后你可以编写这样的测试:

  @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class MyJavaFXApplicationUITest扩展了TestFXBase {

@MockBean
private TemperatureService temperatureService;

@Autowired
private ConfigurableApplicationContext context;

@Override
public void start(阶段阶段)抛出异常{
FXMLLoader loader = new FXMLLoader(getClass()。getResource(main.fxml));
loader.setControllerFactory(context :: getBean);
父rootNode = loader.load();

stage.setScene(new Scene(rootNode,800,600));
stage.centerOnScreen();
stage.show();
}

@Test
public void testTemperatureReading()抛出InterruptedException {
when(temperatureService.getCurrentTemperature())。thenReturn(new Temperature(25.0));
WaitForAsyncUtils.waitForFxEvents();

assertThat(find(#temperatureText,Text.class).getText())。isEqualTo(25.00 C);
}
}

这允许使用模拟服务启动UI。 / p>

I am testing using Spring Boot with JavaFX (Based on some excellent YouTube videos that explain this).

To make it work with TestFX, I need to create the context like this:

@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();
}

I now want to test this JavaFX application, for this I use:

@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"));
    }
}

This starts a Spring context and replaces the "normal" beans with the mock beans as expected.

However, I now get a java.awt.HeadlessException because this 'headless' property is not set to false like is done during normal startup. How to I set this property during the test?

EDIT:

Looking closer it seems that there are 2 context started, one that the Spring testing framework starts and the one I create manually in the init method, so the application under test is not using the mocked beans. If somebody would have a clue how to get the test context reference in the init() method, I would be very happy.

解决方案

The comment from Praveen Kumar pointed in the good direction. When I run the test with -Djava.awt.headless=false, then there is no exception.

To solve the other problem of the 2 Spring contexts, I had to do the following:

Suppose this is your main JavaFx startup class:

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

And for testing, you use this abstract base class (Courtesy of this YouTube video by MVP Java):

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();
    }
}

Then you can write a test like this:

@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");
    }
}

This allows to start the UI using mock services.

这篇关于如何在Spring Boot测试中设置'headless'属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆