Аннотации Spring: Тестирование

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

Вступление

Spring Framework - очень надежный фреймворк, выпущенный в 2002 году. Его основные функции могут применяться к простым Java-приложениям или расширяться до сложных современных веб-приложений.

Поскольку он постоянно обновляется и следует новым парадигмам архитектуры и программирования, он предлагает поддержку многих других фреймворков, которые работают с ним рука об руку.

С таким огромным набором функций вполне нормально, что он знакомит нас с некоторыми новыми аннотациями, которые являются ключевой частью разработки приложений Spring.

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

При этом эта серия статей направлена на раскрытие возможностей, которые вы, как разработчик, должны настраивать и использовать фреймворк Spring:

Аннотации к весеннему тестированию

Разработка через тестирование (TDD) стала важной темой в наши дни, и считается крайне плохой практикой не тестировать ваши приложения должным образом.

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

Чтобы догнать современные практики программирования, Spring запустила новую starter зависимость, spring-boot-starter-test , которая состоит из нескольких фреймворков:

  • JUnit
  • Spring Test и Spring Boot Test
  • AssertJ
  • Hamcrest
  • Mockito
  • JSONassert
  • JsonPath

В этой статье мы рассмотрим следующие тестовые аннотации:

@BootstrapWith

@BootstrapWith - это аннотация, которую вы, скорее всего, будете использовать очень редко. Конфигурации по умолчанию для Spring TestContext Framework более чем достаточно для большинства случаев использования.

Если это не так, вы можете изменить ContextLoader или реализовать собственный TestContext среди множества других конфигураций, которые вы можете изменить.

Опять же, это аннотация, которую вы, вероятно, не будете использовать, если вы не являетесь частью команды, которой действительно нужна настраиваемая конфигурация для Spring TestContext Framework.

@ContextConfiguration

@ContextConfiguration - аннотация интеграционного теста, применяемая на уровне класса для определения того, как Spring должен загружать ApplicationContext .

Эта аннотация может применяться вместе с @Component (а также с аннотациями, такими как @Service , @Repository и т. Д.) @Configuration а также с любым классом, содержащим @Bean s.

Вы можете использовать аннотацию для ссылки либо на файлы XML, либо на классы Java:

 @ContextConfiguration("/some-test-configuration-file.xml") 
 // @ContetConfiguration(locations = "/some-test-configuration-file.xml") 
 // You can use the optional `locations` flag as well. 
 public class ApplicationTests { 
 // Testing code... 
 } 

 @ContextConfiguration(classes = TestConfiguration.class) 
 public class ApplicationTests { 
 // Testing code... 
 } 

Например, допустим, у нас есть TestBean :

 @Configuration 
 public class TestBean { 
 
 @Bean 
 public DeveloperService developerService() { 
 return new DeveloperService(); 
 } 
 } 

Если бы мы хотели сделать некоторые assert для этого bean-компонента, мы бы сделали что-то вроде:

 @ContextConfiguration(classes = TestBean.class) 
 public class ApplicationTests { 
 @Autowired 
 private DeveloperService; 
 
 @Test 
 public void testBean() { 
 Developer dev = developerService.getDeveloperById(5); 
 assertEquals("David", dev.getName()); 
 } 
 } 

В настоящее время предпочтительнее полагаться на классовый подход, поскольку XML обычно считается устаревшим подходом для регистрации bean-компонентов. Если у вас более одного класса, вы, конечно, просто укажите их через classes = {TestBean.class, TestBean2.class, TestBean3.class} и т. Д.

Это подводит нас к @Test , о которой будет подробно рассказано ниже. А пока давайте просто воспользуемся этим в иллюстративных целях.

@WebAppConfiguration

Если вы хотите, чтобы Spring WebApplicationContext для ваших тестов вместо обычного ApplicationContext , вы можете использовать @WebAppConfiguration вместе с аннотацией @ContextConfiguration

 @ContextConfiguration(classes = TestBean.class) 
 @WebAppConfiguration 
 public class ApplicationTests { 
 
 @Autowired 
 private DeveloperService; 
 
 // Rest of the code... 
 } 

В качестве альтернативы вы можете указать value или, скорее, расположение WebApplicationContext , если он не находится в каталоге src/main/webapp

 @WebAppConfiguration("some/other/location") 
 public class ApplicationTests {} 

@ContextHierarchy

Еще одна аннотация, которая обычно используется редко (я лично не видел, чтобы кто-нибудь использовал ее в проекте), - это аннотация @ContextHierarchy

Это позволяет разработчику определять несколько @ContextConfiguration на уровнях через отношения родитель-потомок .

Идея состоит в том, что дочерние контексты могут использовать bean-компоненты, зарегистрированные в родительских контекстах, и это улучшает возможность повторного использования bean-компонентов:

 @ContextHierarchy({ 
 @ContextConfiguration(classes = ApplicationTestConfiguration.class), 
 @ContextConfiguration(classes = WebApplicationTestConfiguration.class) 
 }) 
 public class ApplicationTests { 
 
 } 

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

@ActiveProfiles

@ActiveProfiles - это довольно простая и простая аннотация. Он определяет, какой профиль должен быть активен при загрузке конфигурации контекста:

 @ContextConfiguration 
 @ActiveProfiles("dev") 
 public class ApplicationTests {} 

Это означает, что должен быть активен профиль «dev».

Название аннотации подразумевает, что мы можем определить несколько профилей, которые мы можем:

 @ContextConfiguration 
 @ActiveProfiles({"dev", "prod"}) 
 public class ApplicationTests {} 

Если вы хотите узнать больше о Spring Profiles , мы вам поможем!

@Rollback

Иногда, имея дело с базами данных, мы хотим отменить внесенные нами изменения, особенно если мы вызвали исключение.

@Rollback определяет, должна ли транзакция метода, помеченного @Transactional быть отменена после завершения вызывающего ее метода тестирования.

Его можно применять на уровне класса и метода:

  • Уровень класса : определяет откат по умолчанию для всех методов тестирования в классе.
  • Уровень метода : определяет откат для конкретного метода тестирования.
1
<!-- -->
 @Rollback(true) 
 @Test 
 public void someTest() { 
 // ...calling some transactional method 
 } 

После завершения теста все изменения, внесенные транзакционным методом, будут отменены.

Интересно отметить тот факт, что вы можете установить для необязательного флага значение false , при котором Spring гарантирует, что изменения не будут отменены. Установка для аннотации @Rollback false будет вести себя точно так же, как @Commit .

@Совершить

В дополнение к предыдущему разделу @Commit используется, когда мы хотим гарантировать изменения в базе данных после запуска методов тестирования.

Он ведет себя так же, как @Rollback(false) и может применяться на уровне класса или метода:

 @Commit 
 @Test 
 public void someTest() { 
 // ...calling some transactional method 
 } 

@BeforeTransaction

Иногда мы хотим запустить определенные фрагменты кода до совершения транзакций. Для этого нам, очевидно, нужно определить методы, специально написанные для этого.

Чтобы вызывать их перед каждой транзакцией, мы просто аннотируем их аннотацией @BeforeTransaction

 @BeforeTransaction 
 void methodBeforeTransaction() { 
 // ...ran before a transaction 
 } 

Чтобы аннотация работала правильно, вам необходимо пометить свои транзакционные методы с помощью @Transactional .

Примечание . Начиная с Spring 4.3, эти методы не обязательно должны быть общедоступными.

@AfterTransaction

Имея ту же природу, что и аннотация @BeforeTransaction @AfterTransaction запускает определенный метод после совершения транзакции:

 @AfterTransaction 
 void methodAfterTransaction() { 
 // ...ran after a transaction 
 } 

Примечание . Начиная с Spring 4.3, эти методы не обязательно должны быть общедоступными.

@Sql

Используя @Sql и передавая имена схем, которые мы хотим выполнить, мы можем программно (или декларативно) выполнять сценарии SQL.

По умолчанию эти сценарии @Before перед любыми методами @Before.

Если мы определим сценарий, например createTable.sql :

 CREATE TABLE ITEM (ITEM_ID INT PRIMARY KEY, ITEM_NAME VARCHAR(256) NOT NULL); 

Мы можем ссылаться на него и легко выполнять:

 @Test 
 @Sql("/createTable.sql") 
 public void itemTest { 
 // ...some code that depends on the sql script above 
 } 

@SqlGroup

@SqlGroup позволяет нам объединять несколько сценариев SQL и запускать их.

Если у нас есть другой сценарий, например, для dropTable.sql той же таблицы, dropTable.sql:

 DROP TABLE ITEM; 

Мы можем связать createTable.sql со сценарием dropTable.sql для запуска до и после метода тестирования, например:

 @Test 
 @SqlGroup({ 
 @Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = ""), 
 @Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = ""), 
 }) 
 public void itemTest { 
 // ...item table gets created, tested by the code and then dropped 
 } 

@SqlConfig

Как следует из названия, следуя стандартным примерам аннотаций Spring, аннотация @SqlConfig используется для определения конфигурации сценариев SQL - того, как они анализируются и выполняются.

Его можно применять на уровне класса или метода. Интеграционные тесты, которые требуют глобальной конфигурации для всех запущенных сценариев SQL, обычно используют подход на уровне классов, тогда как подход на уровне методов предназначен для локальных конфигураций определенных методов:

 @Test 
 @Sql(scripts = "/createTable.sql", 
 config = @SqlConfig(attribute = "val", attribute2 = "val")) 
 public void itemTest { 
 // Some code... 
 } 

В аннотацию @SqlConfig можно передать 9 атрибутов:

  • blockCommentEndDelimiter : Конечный разделитель для комментариев блока
  • blockCommentStartDelimiter : начальный разделитель для комментариев блока
  • commentPrefix : префикс для однострочных комментариев.
  • dataSource : Имя bean- dataSource
  • encoding : указание кодировки для скриптов.
  • errorMode : какой режим использовать при обнаружении ошибки
  • separator : символ, используемый для разделения операторов.
  • transactionManager : имя bean-компонента диспетчера транзакций.
  • transactionMode : какой режим использовать при выполнении сценариев SQL.

@SpringBootTest

@SpringBootTest ищет тестовый класс, аннотированный с помощью @SpringBootConfiguration который в большинстве случаев является нашим основным классом приложения, поскольку @SpringBootApplication включает в себя предыдущую аннотацию.

После обнаружения он создает контекст приложения для тестовой среды. Вы даже можете запустить веб-среду, используя атрибут webEnvironment

 @SpringBootTest 
 public class IntegrationTests { 
 // Rest of the code 
 } 
 
 @SpringBootTest(webEnvironment = pringBootTest.WebEnvironment.RANDOM_PORT) 
 public class WebEnvIntegrationTests { 
 // Rest of the code 
 } 

@DataJpaTest

Используя @DataJpaTest , мы можем тестировать приложения JPA. Он применяется на уровне класса и создает контекст приложения для всех @Enitity вместе со встроенной базой данных, которая применяется по умолчанию.

Примечание . Обычные @Component не загружаются в контекст приложения, созданный аннотацией @DataJpaTest

Он используется вместе с @RunWith(SpringRunner.class) , которая указывает, какие средства будут использовать отмеченный класс.

По умолчанию все транзакции JPA будут откатываться (вы можете изменить это поведение, применив либо @Rollback(false) либо @Commit ):

 @RunWith(SpringRunner.class) 
 @DataJpaTest 
 public class SomeJpaTest { 
 // Rest of the code 
 } 

Это классический тест JPA, однако, если вы хотите использовать реальную базу данных, вместо предоставленной встроенной базы данных в памяти, вы можете просто добавить еще одну аннотацию, чтобы предотвратить такое поведение:

 @RunWith(SpringRunner.class) 
 @DataJpaTest 
 @AutoConfigureTestDatabase(replace = Replace.NONE) 
 public class SomeJpaTest { 
 // Rest of the code 
 } 

@DataMongoTest

Очень похоже на @DataJpaTest , для выполнения классических тестов MongoDB мы применяем @DataMongoTest вместе с аннотацией @RunWith(SpringRunner.class) .

Имейте в виду, что эта аннотация используется, когда тест применяется только для тестирования компонентов MongoDB и добавляет только @Document в контекст приложения:

 @RunWith(SpringRunner.class) 
 @DataMongoTest 
 public class SomeMongoTest { 
 // Rest of the code 
 } 

Опять же, если вы хотите запустить это с реальной базой данных, а не со встроенной базой данных в памяти, предоставленной Mongo, вы можете исключить эту опцию:

 @RunWith(SpringRunner.class) 
 @DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class) 
 public class SomeMongoTest { 
 // Rest of the code 
 } 

@WebMvcTest

Опять же, очень похоже на @DataJpaTest и @DataMongoTest , для выполнения классических тестов Spring MVC мы применяем @WebMvcTest вместе с аннотацией @RunWith(SpringRunner.class) .

Имейте в виду, что эффекты этой аннотации применимы только к инфраструктуре MVC. При этом он не создает экземпляр всего контекста.

Аннотацию можно использовать для тестирования одного контроллера, передав его как атрибут, например @WebMvcTest(SomeController.class) .

Чтобы создать экземпляры других необходимых зависимостей, таких как службы, мы обычно используем аннотацию @MockBean @WebMvcTest настраивает MockMvc который можно использовать для простого и быстрого тестирования контроллеров MVC и создания экземпляров других участников:

 @RunWith(SpringRunner.class) 
 @WebMvcTest(HomeController.class) 
 public class ControllerTests { 
 
 // Auto-configured to make mocking easier 
 @Autowired 
 private MockMvc mockMvc; 
 
 @MockBean 
 private SomeBean someBean; 
 
 @Test 
 public void someTest() { 
 // Test logic 
 } 
 } 

@MockBean

При тестировании конкретных модулей, например, контроллера, мы хотим максимально изолировать их. Поскольку большинство компонентов Spring Application зависят от множества других компонентов (зависимостей), квинтэссенцией является обеспечение возможности индивидуального тестирования всех этих компонентов.

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

 @RunWith(SpringRunner.class) 
 @WebMvcTest(HomeController.class) 
 public class ControllerTests { 
 
 // Auto-configured to make mocking easier 
 @Autowired 
 private MockMvc mockMvc; 
 
 @MockBean 
 private SomeBean someBean; 
 
 @Test 
 public void someTest() { 
 // Test logic 
 } 
 } 

В этом примере someBean реальную зависимость. Если компонент существует в контексте, макет заменяет его. Если его не существует, макет добавляется в контекст как bean-компонент.

Примечание . Между аннотациями @Mock и @MockBean @Mock взята из библиотеки Mockito и эквивалентна вызову Mockito.mock() . С другой стороны, @MockBean - это оболочка библиотеки Spring для аннотации @Mock

@AutoConfigureMockMvc

Как следует из названия, @AutoConfigureMockMvc при применении к тестовому классу автоматически настраивает MockMvc , точно так же, как @WebMvcTest автоматически настраивает его.

 @RunWith(SpringRunner.class) 
 @SpringBootTest 
 @AutoConfigureMockMvc 
 public class ControllerTests { 
 
 @Autowired 
 private MockMvc mockMvc; 
 
 // Rest of the logic 
 } 

Если вы хотите сосредоточиться только на веб-слое, рассмотрите возможность использования аннотации @WebMvcTest

@JsonTest

Многие приложения имеют дело с сериализацией / десериализацией JSON . Поэтому при тестировании приложения имеет смысл убедиться, что он работает правильно. Используя @JsonTest , Spring автоматически настраивает поддерживаемый преобразователь JSON (Jackson, Gson или Jsonb).

Обычно он используется вместе с @RunWith(SpringRunner.class) и используется для классических тестов JSON, сканирующих @JsonComponent s.

 @RunWith(SpringRunner.class) 
 @JsonTest 
 public class JsonTests { 
 @Test 
 public void someJsonTest() { 
 // Rest of the logic 
 } 
 } 

@TestPropertySource

@TestPropertySource применяется к уровню класса и определяет расположение источников свойств, которые мы хотим использовать для теста.

Эти свойства сохраняются как набор @PropertySource в среде контекста приложения. Эти свойства имеют приоритет над свойствами системы или приложения.

По сути, когда мы хотим переопределить свойства системы / приложения конкретными свойствами для наших тестов, мы просто аннотируем тестовый класс:

 @RunWith(SpringRunner.class) 
 @ContextConfiguration(classes = TestConfiguration.class) 
 @TestPropertySource("classpath:applicationtest.properties") 
 public class ApplicationTest { 
 // Rest of the logic 
 } 

С другой стороны, вы можете указать встроенные свойства вместо всего файла свойств:

 @RunWith(SpringRunner.class) 
 @ContextConfiguration(classes = TestConfiguration.class) 
 @TestPropertySource(properties = {"sa.website_name = stackabuse", "sa.website_url = www.stackabuse.com"}) 
 public class ApplicationTest { 
 // Rest of the logic 
 } 

@Timed

@Timed определяет время в миллисекундах, в течение которого тестовый метод должен завершить выполнение, иначе он завершится неудачно:

 @Timed(millis = 1000) 
 public void testMethod() { 
 // Some test logic 
 } 

Если на выполнение теста уходит больше секунды, он не сработает. Сюда входят все повторы метода, если @Repeat аннотация @Repeat.

@Повторить

@Repeat определяет, сколько раз следует повторить тестовый метод:

 @Repeat(5) 
 @Test 
 public void testMethod() { 
 // Some test logic 
 } 

Этот тест будет повторен пять раз.

Заключение

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

comments powered by Disqus