2008-11-11 8 views
35

Я работаю над проектом Spring MVC, и у меня есть модульные тесты для всех различных компонентов в исходном дереве.Модульные тесты против тестов интеграции с весной

Например, если у меня есть контроллер HomeController, который должен иметь LoginService впрыскивают в нее, то в моем единичном тесте HomeControllerTest я просто экземпляр объекта в нормальном режиме (за пределами Spring) и придать свойство:

protected void setUp() throws Exception { 
    super.setUp(); 
    //... 
    controller = new HomeController(); 
    controller.setLoginService(new SimpleLoginService()); 
    //... 
} 

Это отлично подходит для тестирования каждого компонента как изолированного устройства - за исключением того, что у меня есть несколько десятков классов в проекте, после написания класса и написания успешного модульного теста для него, я продолжаю забывать обновлять свой Spring MVC контекстный файл, который выполняет фактическую проводку в развернутом приложении. Я узнаю, что забыл обновить файл контекста, когда я развожу проект на Tomcat и найду кучу NullPointers из не связанных с ним компонентов.

Итак, вот мои вопросы:

  1. Это моя первая весна проект - это нормально для создания модульных тестов для отдельных бобов, как я сделал, а затем создать второй набор тестов (интеграционные тесты), чтобы проверить, что все работает так, как ожидалось, с фактическим контекстом приложения? Существует ли для этого наилучшая практика?

  2. Кроме того, как вы отделяете модульные тесты от интеграционных тестов? У меня есть весь исходный код в src, модульные тесты в test - должна ли быть 2-я тестовая папка (например, test-integration) для тестовых примеров интеграции?

Поскольку это моя первая весна проект, мне очень интересно, как другие, как правило, идут о выполнении такого рода вещи - и вместо того, чтобы вновь изобретать колесо я скорее спросить остальную часть сообщества.

ответ

32

Я не могу говорить, что это лучшая практика, но вот что я сделал в прошлом.

испытание Единица измерения:

  • Создание модульных тестов для нетривиальных бобов (то есть, большинство из ваших весной связанных бобов)
  • Используйте издеваются для инжектированных услуг, где это целесообразно (то есть, большинство, если не все время).
  • Используйте стандартное соглашение об именах для этих тестов в каталоге проекта test. Использование Test или TestCase в качестве префикса или суффикса для имени класса, по-видимому, широко практикуется.

Интеграционные тесты:

  • Создание AbstractIntegrationTestCase, который устанавливает SpringWebApplicationContext для использования в тестовых intetgration clases.
  • Используйте соглашение об именах для тестов интеграции в каталоге test. Я использовал IntTest или IntegrationTest в качестве префикса или суффикса для этих тестов.

Настройка три Ant test цели:

  1. тест-все (или что вы хотите назвать его): Run Unit и интеграции тестов
  2. тест: тесты Unit Run (только потому, что test кажется наиболее общеупотребительным для модульного тестирования
  3. тест-интеграции:. запустить интеграционные тесты

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

Что касается отделения блока от интеграционных тестов в отдельный каталог, я не думаю, что это имеет значение, если разработчики и их инструменты могут легко находить и выполнять их.

В качестве примера, последний проект Java, с которым я работал с Spring, использовал именно то, что описано выше, с интеграционными тестами и модульными тестами, живущими в том же каталоге test. С другой стороны, проекты Grails явно разделяют тестовые каталоги единичных и интеграционных тестов в общем тестовом каталоге.

+1

Это звучит неплохо. Но с модульными тестами и интеграционными тестами в тех же самых каталогах нет возможности для Eclipse рассказать им обособленно, не так ли? Единственные опции Eclipse для запуска тестов junit - запустить только один или запустить все в определенной папке - не могут разбить их по имени, например Ant. – 2008-11-11 19:22:38

+0

Мне пришлось вернуться и проверить Eclipse - вы правы, я не вижу способа дифференцировать тесты, если они находятся в одном каталоге. Мой последний проект Spring был выполнен в Idea/Intellij, и это было достаточно долго, что я не помню точно, что такое конфигурация IDE. – 2008-11-11 22:55:10

4

Много утомительных двойных книг с пружиной уходит, если вы также переключитесь на чисто аннотированный режим, где вы комментируете все свои бобы с помощью @Component, @Controller, @Service и @Repository. Просто добавьте @Autowired к атрибутам, которые вам нужно ввести.

См. Раздел 3.11 справочника по весне. http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

В соответствующей заметке мы используем тесты Unit/Integratrion, которые описывают KenG. В моем последнем режиме мы также представили третий «класс» тестов «ComponentTests». Они работают с полной пружинной проводкой, но с проводными реализациями заглушек (с использованием фильтров компонентного сканирования и аннотаций весной).

Причина, по которой мы это делали, заключалась в том, что для некоторого слоя «обслуживания» вы получаете ужасное количество логики проводки с ручной кодировкой, чтобы вручную подключить компонент, а иногда и смешное количество макет-объектов. 100 линий проводки для 5 линий испытания не являются редкостью. Тесты компонентов облегчают эту проблему.

0

Когда я создал интеграционные тесты для веб-приложений, я поместил их в отдельный каталог. Они создаются с использованием jUnit или TestNG и взаимодействуют с тестируемой системой, используя что-то вроде Selenium, которое попадает на веб-страницы, как если бы они были пользователями. Цикл будет выглядеть следующим образом: компиляция, запуск модульных тестов, создание веб-приложения, развертывание его на работающем сервере, выполнение тестов, удаление приложения и получение отчетов. Идея состоит в том, чтобы протестировать всю систему.

2

Используйте интерфейс InitializingBean (реализует метод «afterPropertiesSet») или укажите метод init для ваших компонентов. InitializingBean обычно проще, потому что вам не нужно забывать добавлять метод init к вашим компонентам.

Использование afterPropertiesНастроить для обеспечения того, чтобы все вводилось как ненулевое, если оно равно null, введите исключение.

0

Что касается протестирования отдельных тестов отдельно от тестов интеграции, я помещаю их все в каталог интеграции и тестирования с использованием IDE/Ant с использованием подхода, такого как this. Работает на меня.

6

несколько изолированных точек:

Да, это общий подход к пружинной тестировании - индивидуальная юнит-тесты и интеграционные тесты, где бывшие не загружают контекст Spring.

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

Если вы тестируете проводку в тоннах зависимостей, то они не являются модульными испытаниями. Это интеграционные тесты, в которых вы подключаете зависимости, используя новую, а не зависимую инъекцию. Пустая трата времени и дублирование усилий, когда ваше приложение использует Spring!

Полезные базовые интеграционные тесты для создания контекстов Spring.

Аннотации @required могут помочь вам уловить необходимые зависимости в проводке весны.

Возможно, загляните в Maven, который даст вам явные фазы для привязки вашего устройства и тестов интеграции. Maven довольно широко используется в сообществе Spring.

0

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