Подтвердить что ты не робот

Модульные тесты и тесты интеграции с Spring

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Единичные тесты:

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

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

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

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

  • test-all (или что-то еще, что вы хотите назвать): Run Unit и Integration Tests
  • test: выполнить тесты модуля (только потому, что test, по-видимому, является наиболее распространенным использованием для модульного тестирования
  • test-integration: выполните тесты интеграции.

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

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

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

Ответ 2

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

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

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

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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