Тестирование переопределенного EventHandler в Java (JavaFx, Spring Boot) - PullRequest
2 голосов
/ 26 февраля 2020

Я писал небольшое приложение на Java, используя Spring Boot с интерфейсом JavaFX.

У меня проблемы с разработкой, как проверить часть одного из контроллеров. В частности, контроллер включает в себя некоторую обработку событий, когда нажата кнопка «подтвердить» или «отменить». Нажатие подтверждения должно привести к удалению выбранного элемента из базы данных и просмотра таблицы. Нажатие любой кнопки должно привести к закрытию текущего окна.

package application.controllers;

import ...

@Controller
public class ConfirmDeleteController {

    @FXML private Label labelConfirmDelete;
    @FXML private Button confirmButton;
    @FXML private Button cancelButton;

    private FooService fooService;
    private TableView<Foo> fooTable;
    private Foo foo = new foo();


    void initData(TableView<Foo> fooTable, FooService fooService) {

        this.fooTable = fooTable;
        this.fooService = fooService;

        foo = (Foo) fooTable.getSelectionModel().getSelectedItem();     

        [other irrelevant bits with test coverage already]

        initializeButtonEventHandling();
    }


    private void initializeButtonEventHandling() {

        confirmButton.defaultButtonProperty().bind(confirmButton.focusedProperty());
        cancelButton.defaultButtonProperty().bind(cancelButton.focusedProperty());

        confirmButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                fooService.delete(foo); // Delete from db
                fooTable.getItems().remove(foo);    // Delete from the table view                           
                confirmButton.getScene().getWindow().hide(); // Close this pop up
            }
        });

        cancelButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                cancelButton.getScene().getWindow().hide();
            }
        });
    }
}

Для теста у меня есть:

public class TestConfirmDeleteController extends ApplicationTest {  

    @Mock private Foo foo;
    @Mock private FooService fooService;
    @Mock private TableViewSelectionModel<Foo> selectionModel;
    @Mock private TableView<Foo> fooTable;

    private ConfirmDeleteController confirmDeleteController;

    @Override
    public void start (Stage stage) throws Exception {

        // Mock core behaviour
        initMocks(this);    
        when(fooTable.getSelectionModel()).thenReturn(selectionModel);
        when(selectionModel.getSelectedItem()).thenReturn(foo);


        // Load and display
        FXMLLoader fxmlLoader = new FXMLLoader(
                getClass().getResource("/fxml/popups/ConfirmDelete.fxml"));

        stage.setScene(new Scene((Pane) fxmlLoader.load()));

        confirmDeleteController = 
                fxmlLoader.<ConfirmDeleteController>getController();

        stage.show();
    }


...

    @SuppressWarnings("unchecked")
    @Test
    public void testConfirmDeletion() {

        // Given
        ObservableList<Foo> listOfFoo = mock(ObservableList.class);
        Scene scene = mock(Scene.class);
        Window window = mock(Window.class);

        when(fooTable.getItems()).thenReturn(listOfFoo);
        when(listOfFoo.remove(foo)).thenReturn(true);
        when(scene.getWindow()).thenReturn(window);

        // When
        confirmDeleteController.initData(fooTable, fooService);
        clickOn("#confirmButton");


        // Then
        verify(fooService).delete(foo); // Delete from database
        verify(listOfFoo).remove(foo); // Delete from TableView
        verify(window).hide(); // Close the confirm delete window
    }

Я пробовал несколько способов запустить событие, но мне не повезло , Я попытался заменить кнопку на макет, ввести ее, а затем запустить событие напрямую. Я попытался с помощью робота TestFX нажать кнопку (как указано выше). В этом случае вы можете ПРОСМОТРЕТЬ робота, нажав кнопку, но утверждения не пройдены, что указывает на то, что выбранный элемент не удален и т. Д. c

Каждый подход ощущается как «плохо выполненный интеграционный тест-esque», и поэтому я чувствую, что мне, возможно, даже потребуется реорганизовать его, чтобы переместить обработку событий в другое место?

Может, кто-нибудь посоветует, как решить эту проблему и получить надлежащее тестовое покрытие? На этом этапе я бьюсь головой об стену.

Я ЗНАЮ, что код работает, так как я тщательно тестировал его вручную, но не могу понять, как его тестировать.

Спасибо.

Редактировать: Теперь я выяснил, что проблема на самом деле связана с настройками безопасности и конфиденциальности на моей Ma c. Смотри ниже.

1 Ответ

0 голосов
/ 02 марта 2020

В случае, если кто-то заинтересован в будущем, проблема здесь фактически связана с настройками безопасности и конфиденциальности на ОС Ma c Catalina. У Eclipse не было разрешения на управление компьютером (Настройки -> Безопасность и конфиденциальность -> Специальные возможности -> «Разрешить приложениям ниже управлять вашим компьютером».

В результате FxRobot фактически не смог нажмите кнопку. Вы могли видеть движение мыши, но в результате ничего не произошло.

Обновление настроек, как указано выше, перезапуск Eclipse и повторный запуск теста позволили тесту фактически нажимать кнопки, и затем события произошли, как и ожидалось.

...