-
Notifications
You must be signed in to change notification settings - Fork 3
Description
The three most common scenarios I can think off for using FXComponentTest are:
-
Test a programatically created component (as seen in the FX Test example)
-
Test a component initialized from a FXML file, instantiated with the controller class (if defined in the fxml file, obviously).
-
Test a component initialized from a FXML file, instantiated with a mocked controller.
For the last 2 scenarios, FXComponentTest could easily provide helper methods. The following code could be added to FXComponentTest (and is compatible with issues #17 and #19):
private static final Pattern FXML_CONTROLLER_PATTERN = Pattern.compile("\\sfx:controller=\\\".+\\\"");
protected O loadFromFXML(final String fxmlFileName) throws IOException {
final URL location = getClass().getResource(fxmlFileName);
final FXMLLoader loader = new FXMLLoader(location);
return loader.load();
}
protected O loadFromFXML(final String fxmlFileName, final Object controller) throws IOException, URISyntaxException {
final FXMLLoader loader = new FXMLLoader();
loader.setController(controller);
return loader.load(getControllerStrippedFxml(fxmlFileName));
}
private InputStream getControllerStrippedFxml(final String fxmlFileName) throws IOException, URISyntaxException {
final ByteArrayOutputStream fileContent = new ByteArrayOutputStream();
final StringBuffer strippedContent = new StringBuffer();
final Matcher matcher;
try (InputStream is = getClass().getResource(fxmlFileName).openStream()) {
byte[] chunk = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(chunk)) > 0) {
fileContent.write(chunk, 0, bytesRead);
}
}
matcher = FXML_CONTROLLER_PATTERN.matcher(fileContent.toString());
while (matcher.find()) {
matcher.appendReplacement(strippedContent, "");
}
matcher.appendTail(strippedContent);
return new ByteArrayInputStream(strippedContent.toString().getBytes());
}
The above code would allow a user of FXComponentTest create a component just just a few lines of code. For example, suppose I want to test a Pane defined by a fxml file inserted into a BorderPane:
@RunWith(FXRunner.class)
public class MyViewTest extends FXComponentTest<BorderPane, Pane> {
//other methods here
@Override
protected Pane createComponent(final BorderPane parent) throws IOException {
final Pane pane = loadFromFXML("myView.fxml");
parent.setCenter(pane);
return pane;
}
}
If I want to test the view with a custom controller (mock/stub/spy) then the class would look like:
@RunWith(FXRunner.class)
public class MyViewTest extends FXComponentTest<BorderPane, Pane> {
final MyController controller = //controller creation here
//other methods here
@Override
protected Pane createComponent(final BorderPane parent) throws IOException, , URISyntaxException {
final Pane pane = loadFromFXML("myView.fxml", controller);
parent.setCenter(pane);
return pane;
}
}
The added benefit of easily creating a component with a custom controller is that test would be really easy if the user decides to use the PMVC pattern for designing the views.