2016-09-01 55 views
2

我正在使用Spring Boot和JavaFX進行測試(基於解釋這個的some excellent YouTube videos)。如何在Spring Boot測試中設置'無頭'屬性?

,使其與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上下文並按照預期用模擬bean替換「正常」的bean。

但是,我現在得到一個java.awt.HeadlessException,因爲這個'headless'屬性沒有像正常啓動時那樣設置爲false。如何在測試期間設置此屬性?

編輯:

更仔細地觀察,似乎有2個方面開始,一個春節測試框架開始和一個我在init方法手動創建,所以測試的應用程序未使用嘲笑豆。如果有人想知道如何獲得init()方法中的測試環境參考,我會非常高興。

+1

可能是[link](http://stackoverflow.com/questions/36160353/why-does-swing-think-its-headless-under-spring-boot-but-not-under-spring-or- pl)會幫助你。 –

回答

3

Praveen Kumar的評論指出了良好的方向。當我用-Djava.awt.headless=false運行測試時,則沒有例外。

爲了解決2個春天上下文的其他問題,我必須做到以下幾點:

想這是你的主了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; 
    } 
} 

並進行測試,使用這種抽象基類(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(); 
    } 
} 

然後,你可以寫這樣一個測試:

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

這允許使用模擬服務啓動UI。

相關問題