Обработка событий Swing в тесте JUnit

У меня есть Java-приложение Swing с сетевыми соединениями с несколькими «Игроками», которые представлены как объекты игрока, каждый со своим собственным потоком связи. В приложении есть объект «Команда», управляющий всеми объектами игрока. Несколько компонентов пользовательского интерфейса прослушивают события, передаваемые от игроков через объект Team.

В моем проекте командный объект инициирует все события в потоке Swing с помощью invokeLater, так что остальной части моего приложения не нужно беспокоиться о проблемах с потоками. Однако я не знаю, как я могу протестировать класс Team в тесте JUnit.

Еще немного фона. Сначала у меня был объект Team, запускающий свои события в потоках объекта игрока (вообще без переключения потоков). Модульный тест команды прошел успешно, но я столкнулся со многими проблемами с потоками в своем пользовательском интерфейсе с помощью invokeLaters и синхронизировался повсюду. Затем я решил упростить модель многопоточности, запустив события запуска объектов Team в потоке Swing, но теперь модульный тест Team не проходит, потому что он не получает события. Что делать?

Решение, которое приходит на ум, состоит в том, чтобы ввести дополнительный объект поверх Team, который переключает потоки и сохраняет исходный модульный тест нетронутым, но мне не нравится идея усложнять производственный код только для того, чтобы модульный тест был успешным.


person Emile    schedule 30.11.2008    source источник


Ответы (3)


Когда я провел тестирование JUnit с помощью EventQueue.invokeLater, я отделился от этой зловещей статики. Создайте интерфейс с invokeLater и isDispatchThread методами. Для производства реализация должна просто перенаправить на EventQueue. Для тестирования используйте свой собственный поток (который можно настроить и снести для каждого теста).

Еще несколько случайных советов:

  • Держите графический интерфейс как можно более тонким.
  • Держите потоки вне всего остального и все остальное вне потоков.
  • С подозрением относитесь ко всему, что утверждается как потокобезопасное.
person Tom Hawtin - tackline    schedule 30.11.2008
comment
Мне нравится ваш совет, особенно второй. Ваше предложение ввести интерфейс, вероятно, является правильным. Тем не менее, я чувствую себя немного неловко, что я должен сделать это только для того, чтобы что-то проверить. - person Emile; 01.12.2008

Возможно, вы можете использовать easymock, чтобы изолировать классы, которые вы хотите протестировать, и сделать так, чтобы фиктивные объекты получали события и проверяли, что они запущены.

Я бы рекомендовал EasyMock: http://www.easymock.org/

Из вашей истории кажется, что ваши юнит-тесты - это больше интеграционные тесты и очень сложные. Если это так, постарайтесь упростить и изолировать. Вы, вероятно, читали http://junit.sourceforge.net/doc/testinfected/testing.htm

Надеюсь, это поможет.

person Rolf    schedule 30.11.2008
comment
Вы правы, что я тестирую более одного класса. Чего я пытаюсь достичь, так это убедиться, что связь между несколькими процессами работает на уровне команды. Это взаимодействие между объектами, которые я хочу проверить, и мне нужно подумать, чтобы найти другой способ. Спасибо за совет. - person Emile; 01.12.2008

Решение, которое приходит на ум, состоит в том, чтобы ввести дополнительный объект поверх Team, который переключает потоки и сохраняет исходный модульный тест нетронутым, но мне не нравится идея усложнять производственный код только для того, чтобы модульный тест был успешным.

Я не знаю, так ли это здесь, но я часто обнаруживаю, что «сложность», которую я добавляю, на самом деле является более высоким уровнем абстракции, улучшающим код.

Первоначальная идея фиктивных объектов заключалась не в том, чтобы упростить модульное тестирование, а в том, чтобы «обнаружить интерфейс», создать интерфейсы, которые представляют абстракции вашего вездесущего языка, а не работать на уровне API.

person Jeffrey Fredrick    schedule 30.11.2008
comment
Я согласен со сложностью и функциональной абстракцией, но в данном случае я имею дело только с проблемами многопоточности, которые можно довольно легко решить, выполняя большинство действий в потоке пользовательского интерфейса, за исключением того, что это усложняет тестирование. Спасибо, что заставили меня переосмыслить мои абстракции! - person Emile; 01.12.2008