如何设置无头' Spring Boot测试中的属性?

时间:2016-09-01 07:39:07

标签: java javafx spring-boot spring-test testfx

我正在测试使用Spring Boot with JavaFX(基于some excellent YouTube videos解释这一点)。

要使其与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();
}

我现在想测试这个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"));
    }
}

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

然而,我现在得到一个java.awt.HeadlessException,因为这个“无头”'如正常启动时所做的那样,属性不会设置为false。如何在测试期间设置此属性?

编辑:

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

2 个答案:

答案 0 :(得分:3)

Praveen Kumar的评论指出了良好的方向。当我使用<!DOCTYPE HTML> <html> <head> <!--<link rel="stylesheet"type="text/css" href="newellipse.css"> <script src="jfile/myquery.js"></script>--> <meta charset="UTF-8"> </head> <body> <input id="ipvalue" type="text" value="25x^2+4y^2+100x-40y=-100"> <button onclick="checkFruit()">solve</button> <p id="demo"></p> <p id="demo1"></p> <p id="demo2"></p> <p id="demo3"></p> <p id="demo4"></p> <canvas id="myCanvas"width="578" height="400" style="position:absolute;left:220px;top:50px;"></canvas> <script> var canvas = document.querySelector("#myCanvas"); var context2d = canvas.getContext("2d"); var step = 2*Math.PI/1000; // see note 1 var h = 150; var k = 150; var r = 80; context2d.beginPath(); //tell canvas to start a set of lines for(var theta = 0; theta < 2*Math.PI; theta += step) { var x = h + r*Math.cos(theta); var y = k - 0.5 * r*Math.sin(theta); //note 2. context2d.lineTo(x,y); } context2d.closePath(); //close the end to the start point context2d.stroke(); //actually draw the accumulated lines var splitter = /([\-+])?\s*(\d+)?([a-zA-Z])\b/g; var source = document.querySelector('#ipvalue'); var target = document.querySelector("#demo"); var target1 = document.querySelector("#demo1"); var target2 = document.querySelector("#demo2"); var target3 = document.querySelector("#demo3"); var target4 = document.querySelector("#demo4"); function checkFruit() { var equation = splitter.exec(source.value); console.log('SOURCE: ', source.value); console.log('EQUATION: ', equation); console.log('SUGGESTION: ', source.value.match(splitter)); var y = source.value; switch(y) { case "25x^2+4y^2+100x-40y=-100": var text = "Formula for Ellipse x^2/a^2+y^2/b^2=1"; var text1 = "First RHS side value consider for 1"; var text2 = "LHS side divide by RHS value for 16"; var text3 = "Take a square root of denaminater value"; var text4 = "Find the x and y value"; target.innerHTML = text; target1.innerHTML = text1; target2.innerHTML = text2; target3.innerHTML = text3; target4.innerHTML = text4; break; } } </script> </body> <html> 运行测试时,没有例外。

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

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

-Djava.awt.headless=false

对于测试,您使用此抽象基类(jQuery):

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

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

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

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

答案 1 :(得分:0)

@SpringBootTest 使用 SpringBootContextLoader 类作为上下文加载器,因此可以通过以下方法从方法SpringBootContextLoader.loadContext加载ApplicationContext:

SpringApplication application = getSpringApplication();
......
return application.run();

调用方法application.run()时,应用程序使用其内部无头属性配置系统无头属性。

因此,如果我们想在Spring Boot测试中设置'headless'属性,只需创建一个自定义的特定ContextLoader类扩展SpringBootContextLoader类,并使用set方法覆盖方法getSpringApplication headless属性为false,然后为特定的ContextLoader分配@SpringBootTest批注@ContextConfiguration。代码:

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() {

    }

}