Компоненты микросервисной архитектуры
Микросервисная архитектура включает множество компонентов, которые обеспечивают её функциональность, масштабируемость и устойчивость. Разберём ключевые элементы, не повторяя уже упомянутые аспекты, и сосредоточимся на архитектурных и инфраструктурных компонентах.
1. API Gateway
API Gateway — это точка входа для клиентов в микросервисную архитектуру. Он обрабатывает все запросы от внешних приложений и маршрутизирует их к соответствующим микросервисам.
Основные функции:
Маршрутизация запросов: Отправляет запросы к нужным микросервисам.
Агрегация данных: Собирает данные от нескольких сервисов и возвращает единый ответ клиенту.
Безопасность: Реализует аутентификацию и авторизацию, ограничивает доступ к ресурсам.
Кэширование: Ускоряет ответы на повторяющиеся запросы.
Обработка ошибок: Преобразует ошибки микросервисов в понятный клиентам формат.
2. Service Discovery
В микросервисной архитектуре сервисы могут динамически добавляться или удаляться. Service Discovery помогает находить доступные сервисы в распределённой системе.
Основные компоненты:
Service Registry: Хранилище, где регистрируются все доступные сервисы (например, Eureka, Consul, Zookeeper).
Service Provider: Микросервис, который регистрируется в реестре.
Service Consumer: Клиент, который запрашивает информацию о доступных сервисах.
Подходы к Service Discovery:
Client-Side Discovery: Клиент напрямую взаимодействует с реестром и выбирает сервис.
Server-Side Discovery: API Gateway или балансировщик нагрузки управляет взаимодействием с реестром.
3. Load Balancer (Балансировщик нагрузки)
Балансировка нагрузки — важный компонент для распределения запросов между несколькими экземплярами одного микросервиса.
Она обеспечивает:
Распределение нагрузки: Запросы равномерно направляются на экземпляры.
Высокую доступность: Отказ одного экземпляра не влияет на работоспособность системы.
Масштабируемость: Добавление новых экземпляров происходит прозрачно.
Виды балансировки:
Client-Side Load Balancing:
Клиент решает, на какой экземпляр направить запрос.
Инструменты: Spring Cloud LoadBalancer, Ribbon.
Server-Side Load Balancing:
Балансировщик нагрузки (например, Nginx, AWS Elastic Load Balancer) решает, куда отправить запрос.
4. Configuration Management
Конфигурация микросервисов должна быть централизованной и управляемой. Для этого используется Configuration Management, который хранит настройки, такие как параметры подключения к базам данных, порты и ключи API.
Основные требования:
Централизованное хранилище конфигурации.
Поддержка профилей (например, dev, staging, production).
Безопасное хранение конфиденциальных данных (шифрование).
Spring Cloud Config:
Spring Cloud Config позволяет управлять конфигурацией через Git-репозиторий.
Пример конфигурации в Git:
Клиентское приложение подключается к Config Server:
5. Centralized Logging (Централизованное логирование)
При распределённой архитектуре логи микросервисов должны быть централизованы, чтобы упрощать отладку и мониторинг.
Компоненты логирования
Логирование на уровне микросервиса:
Используются библиотеки логирования (Logback, SLF4J).
Структурированные логи (JSON) упрощают анализ.
Централизованный сбор логов:
Инструменты: ELK-стек (Elasticsearch, Logstash, Kibana), Graylog.
Трассировка запросов:
Инструменты: Spring Cloud Sleuth, Zipkin.
6. Monitoring and Metrics (Мониторинг и метрики)
Мониторинг микросервисов помогает следить за их производительностью и выявлять проблемы. Это достигается с помощью сбора метрик и создания дашбордов.
Популярные инструменты:
Prometheus: Для сбора и анализа метрик.
Grafana: Для визуализации данных.
Spring Actuator: Для сбора метрик и состояния приложения.
#Java #Training #Spring #Components_Microservices
Микросервисная архитектура включает множество компонентов, которые обеспечивают её функциональность, масштабируемость и устойчивость. Разберём ключевые элементы, не повторяя уже упомянутые аспекты, и сосредоточимся на архитектурных и инфраструктурных компонентах.
1. API Gateway
API Gateway — это точка входа для клиентов в микросервисную архитектуру. Он обрабатывает все запросы от внешних приложений и маршрутизирует их к соответствующим микросервисам.
Основные функции:
Маршрутизация запросов: Отправляет запросы к нужным микросервисам.
Агрегация данных: Собирает данные от нескольких сервисов и возвращает единый ответ клиенту.
Безопасность: Реализует аутентификацию и авторизацию, ограничивает доступ к ресурсам.
Кэширование: Ускоряет ответы на повторяющиеся запросы.
Обработка ошибок: Преобразует ошибки микросервисов в понятный клиентам формат.
2. Service Discovery
В микросервисной архитектуре сервисы могут динамически добавляться или удаляться. Service Discovery помогает находить доступные сервисы в распределённой системе.
Основные компоненты:
Service Registry: Хранилище, где регистрируются все доступные сервисы (например, Eureka, Consul, Zookeeper).
Service Provider: Микросервис, который регистрируется в реестре.
Service Consumer: Клиент, который запрашивает информацию о доступных сервисах.
Подходы к Service Discovery:
Client-Side Discovery: Клиент напрямую взаимодействует с реестром и выбирает сервис.
Server-Side Discovery: API Gateway или балансировщик нагрузки управляет взаимодействием с реестром.
3. Load Balancer (Балансировщик нагрузки)
Балансировка нагрузки — важный компонент для распределения запросов между несколькими экземплярами одного микросервиса.
Она обеспечивает:
Распределение нагрузки: Запросы равномерно направляются на экземпляры.
Высокую доступность: Отказ одного экземпляра не влияет на работоспособность системы.
Масштабируемость: Добавление новых экземпляров происходит прозрачно.
Виды балансировки:
Client-Side Load Balancing:
Клиент решает, на какой экземпляр направить запрос.
Инструменты: Spring Cloud LoadBalancer, Ribbon.
Server-Side Load Balancing:
Балансировщик нагрузки (например, Nginx, AWS Elastic Load Balancer) решает, куда отправить запрос.
4. Configuration Management
Конфигурация микросервисов должна быть централизованной и управляемой. Для этого используется Configuration Management, который хранит настройки, такие как параметры подключения к базам данных, порты и ключи API.
Основные требования:
Централизованное хранилище конфигурации.
Поддержка профилей (например, dev, staging, production).
Безопасное хранение конфиденциальных данных (шифрование).
Spring Cloud Config:
Spring Cloud Config позволяет управлять конфигурацией через Git-репозиторий.
Пример конфигурации в Git:
# application.yml
database:
url: jdbc:postgresql://localhost:5432/mydb
username: user
password: secret
Клиентское приложение подключается к Config Server:
spring.config.import=configserver:http://localhost:8888
5. Centralized Logging (Централизованное логирование)
При распределённой архитектуре логи микросервисов должны быть централизованы, чтобы упрощать отладку и мониторинг.
Компоненты логирования
Логирование на уровне микросервиса:
Используются библиотеки логирования (Logback, SLF4J).
Структурированные логи (JSON) упрощают анализ.
Централизованный сбор логов:
Инструменты: ELK-стек (Elasticsearch, Logstash, Kibana), Graylog.
Трассировка запросов:
Инструменты: Spring Cloud Sleuth, Zipkin.
6. Monitoring and Metrics (Мониторинг и метрики)
Мониторинг микросервисов помогает следить за их производительностью и выявлять проблемы. Это достигается с помощью сбора метрик и создания дашбордов.
Популярные инструменты:
Prometheus: Для сбора и анализа метрик.
Grafana: Для визуализации данных.
Spring Actuator: Для сбора метрик и состояния приложения.
#Java #Training #Spring #Components_Microservices
7. Circuit Breaker (Схема предохранителя)
Circuit Breaker защищает систему от cascade failures (каскадных отказов). Если один сервис недоступен, Circuit Breaker предотвращает повторные запросы и возвращает заранее определённый ответ.
Инструменты:
Resilience4j: Легковесная библиотека для обработки отказов.
Hystrix (устаревший): Предыдущий стандарт для реализации Circuit Breaker.
8. Event-Driven Architecture
Микросервисы могут взаимодействовать друг с другом асинхронно через события. Это полезно для реализации реактивных и loosely coupled систем.
Основные инструменты:
Apache Kafka: Распределённая потоковая платформа.
RabbitMQ: Брокер сообщений для обмена событиями.
Spring Cloud Stream: Абстракция для работы с системами обмена сообщениями.
Пример работы с Kafka
Отправка события:
Получение события:
9. Database Per Service (База данных для каждого сервиса)
В микросервисной архитектуре каждый сервис имеет собственную базу данных, чтобы избежать проблем с согласованностью данных и зависимостями.
Собственная база данных:
Каждый сервис использует отдельную базу (например, PostgreSQL для одного сервиса и MongoDB для другого).
Общая база с логической изоляцией:
Используются отдельные схемы базы данных.
10. Security Components
Безопасность в микросервисах сложнее, так как система состоит из множества независимых компонентов.
Подходы к безопасности
Authentication and Authorization:
Использование OAuth2 и OpenID Connect.
Spring Security + Keycloak или Auth0.
Secure Communication:
Шифрование трафика с помощью TLS/SSL.
API Security:
Валидация входящих запросов.
Ограничение доступа с использованием JWT (JSON Web Tokens).
#Java #Training #Spring #Components_Microservices
Circuit Breaker защищает систему от cascade failures (каскадных отказов). Если один сервис недоступен, Circuit Breaker предотвращает повторные запросы и возвращает заранее определённый ответ.
Инструменты:
Resilience4j: Легковесная библиотека для обработки отказов.
Hystrix (устаревший): Предыдущий стандарт для реализации Circuit Breaker.
8. Event-Driven Architecture
Микросервисы могут взаимодействовать друг с другом асинхронно через события. Это полезно для реализации реактивных и loosely coupled систем.
Основные инструменты:
Apache Kafka: Распределённая потоковая платформа.
RabbitMQ: Брокер сообщений для обмена событиями.
Spring Cloud Stream: Абстракция для работы с системами обмена сообщениями.
Пример работы с Kafka
Отправка события:
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
public void publishEvent(String topic, String message) {
kafkaTemplate.send(topic, message);
}
Получение события:
@KafkaListener(topics = "user-events", groupId = "group_id")
public void consume(String message) {
System.out.println("Received message: " + message);
}
9. Database Per Service (База данных для каждого сервиса)
В микросервисной архитектуре каждый сервис имеет собственную базу данных, чтобы избежать проблем с согласованностью данных и зависимостями.
Собственная база данных:
Каждый сервис использует отдельную базу (например, PostgreSQL для одного сервиса и MongoDB для другого).
Общая база с логической изоляцией:
Используются отдельные схемы базы данных.
10. Security Components
Безопасность в микросервисах сложнее, так как система состоит из множества независимых компонентов.
Подходы к безопасности
Authentication and Authorization:
Использование OAuth2 и OpenID Connect.
Spring Security + Keycloak или Auth0.
Secure Communication:
Шифрование трафика с помощью TLS/SSL.
API Security:
Валидация входящих запросов.
Ограничение доступа с использованием JWT (JSON Web Tokens).
#Java #Training #Spring #Components_Microservices
Введение в тестирование в Spring
Основы тестирования
Тестирование — это ключевой этап разработки, позволяющий удостовериться в правильности работы приложения. Без качественных тестов сложно поддерживать стабильность приложения, особенно с ростом функциональности. Рассмотрим основные понятия тестирования и их важность.
Виды тестирования
Юнит-тесты (Unit Tests):
Тестируют отдельные модули или компоненты приложения, такие как методы или классы.
Основная цель — проверка логики отдельно взятого компонента.
Пример: Проверка корректности метода расчёта.
Интеграционные тесты (Integration Tests):
Проверяют взаимодействие между различными компонентами приложения (например, контроллер ↔️ сервис ↔️ база данных).
Цель — убедиться, что компоненты работают совместно.
Функциональные тесты (Functional Tests):
Проверяют функциональность приложения с точки зрения пользователя.
Пример: Убедиться, что REST API возвращает ожидаемые данные.
Энд-ту-энд тесты (E2E Tests):
Покрывают весь процесс использования приложения, от начала до конца.
Используются для проверки полного пользовательского сценария.
Пирамида тестирования
В идеале, проект должен иметь:
Много юнит-тестов.
Умеренное количество интеграционных тестов.
Немного функциональных и E2E тестов.
Это помогает балансировать между скоростью тестирования и его надежностью.
Инструменты тестирования
Spring предоставляет мощный набор инструментов для тестирования. Ключевые библиотеки и фреймворки:
JUnit 5 (Jupiter):
Основной фреймворк для написания юнит-тестов в Java.
Обеспечивает аннотации для написания и управления тестами.
Mockito:
Используется для создания моков (объектов-заглушек), которые эмулируют поведение реальных зависимостей.
Упрощает тестирование компонентов с зависимостями.
Spring Test:
Расширяет возможности JUnit и Mockito для работы с контекстом Spring.
Позволяет тестировать компоненты Spring (например, бины, репозитории, сервисы) в интеграционном контексте.
#Java #Training #Spring #Testing
Основы тестирования
Тестирование — это ключевой этап разработки, позволяющий удостовериться в правильности работы приложения. Без качественных тестов сложно поддерживать стабильность приложения, особенно с ростом функциональности. Рассмотрим основные понятия тестирования и их важность.
Виды тестирования
Юнит-тесты (Unit Tests):
Тестируют отдельные модули или компоненты приложения, такие как методы или классы.
Основная цель — проверка логики отдельно взятого компонента.
Пример: Проверка корректности метода расчёта.
Интеграционные тесты (Integration Tests):
Проверяют взаимодействие между различными компонентами приложения (например, контроллер ↔️ сервис ↔️ база данных).
Цель — убедиться, что компоненты работают совместно.
Функциональные тесты (Functional Tests):
Проверяют функциональность приложения с точки зрения пользователя.
Пример: Убедиться, что REST API возвращает ожидаемые данные.
Энд-ту-энд тесты (E2E Tests):
Покрывают весь процесс использования приложения, от начала до конца.
Используются для проверки полного пользовательского сценария.
Пирамида тестирования
В идеале, проект должен иметь:
Много юнит-тестов.
Умеренное количество интеграционных тестов.
Немного функциональных и E2E тестов.
Это помогает балансировать между скоростью тестирования и его надежностью.
Инструменты тестирования
Spring предоставляет мощный набор инструментов для тестирования. Ключевые библиотеки и фреймворки:
JUnit 5 (Jupiter):
Основной фреймворк для написания юнит-тестов в Java.
Обеспечивает аннотации для написания и управления тестами.
Mockito:
Используется для создания моков (объектов-заглушек), которые эмулируют поведение реальных зависимостей.
Упрощает тестирование компонентов с зависимостями.
Spring Test:
Расширяет возможности JUnit и Mockito для работы с контекстом Spring.
Позволяет тестировать компоненты Spring (например, бины, репозитории, сервисы) в интеграционном контексте.
#Java #Training #Spring #Testing
Что выведет код
#Tasks
public class Task251224_1 {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 5; i++) {
sum += i;
}
System.out.println(sum);
}
}
#Tasks
Написание первого теста
Рассмотрим пример класса, который нужно протестировать:
Теперь напишем тест для метода add:
Разбор кода
Ключевые элементы:
@Test — помечает метод как тестовый.
Assertions.assertEquals — проверяет, что результат равен ожидаемому значению.
Результат:
Если метод возвращает 8, тест пройдет успешно.
Если результат другой, будет выдано сообщение об ошибке.
Это элементарный тест который показывает насколько одновременно проста и важна сфера тестирования приложения.
#Java #Training #Spring #Testing
Рассмотрим пример класса, который нужно протестировать:
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
}
Теперь напишем тест для метода add:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class CalculatorTest {
@Test
void testAddition() {
Calculator calculator = new Calculator();
int result = calculator.add(5, 3);
Assertions.assertEquals(8, result, "Addition should return correct result");
}
}
Разбор кода
Ключевые элементы:
@Test — помечает метод как тестовый.
Assertions.assertEquals — проверяет, что результат равен ожидаемому значению.
Результат:
Если метод возвращает 8, тест пройдет успешно.
Если результат другой, будет выдано сообщение об ошибке.
Это элементарный тест который показывает насколько одновременно проста и важна сфера тестирования приложения.
#Java #Training #Spring #Testing
Пишем тестовое задание от реального работодателя. Часть II. Встреча от 25.12.2024
Запись нашей встречи -
YOUTUBE
RUTUBE
Крайне благодарен всем кто пришел, за участие!💪
На встрече мы продолжили писать тестовый сервис по документации реального работодателя с hh.ru:
— доразбирали логику методов
— написали тесты в разных вариантах
— нафигачили кучу ошибок и потратили время на их поиск и попытки устранить😂🤪
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Всем хорошего настроения! 🫡✌️
Запись нашей встречи -
YOUTUBE
RUTUBE
Крайне благодарен всем кто пришел, за участие!💪
На встрече мы продолжили писать тестовый сервис по документации реального работодателя с hh.ru:
— доразбирали логику методов
— написали тесты в разных вариантах
— нафигачили кучу ошибок и потратили время на их поиск и попытки устранить😂🤪
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Всем хорошего настроения! 🫡✌️
Аннотации JUnit 5
Структура JUnit 5
JUnit 5 (также известный как Jupiter) предоставляет богатый набор аннотаций для управления тестами. Каждая из аннотаций служит определенной цели — от настройки окружения до группировки и выполнения тестов.
Состоит из следующих модулей:
JUnit Platform: Основная платформа для запуска тестов.
JUnit Jupiter: Новый API для написания тестов.
JUnit Vintage: Обеспечивает совместимость с JUnit 4.
Аннотации для организации тестов
@Test
Используется для обозначения метода как тестового.
Этот метод должен быть public или default.
Пример:
@DisplayName
Устанавливает читаемое имя для теста, которое будет отображаться в отчетах.
Пример:
@Disabled
Отключает тест, чтобы он не выполнялся.
Можно указать причину отключения.
Пример:
Аннотации для управления жизненным циклом тестов
@BeforeEach
Выполняется перед каждым тестом.
Используется для подготовки окружения.
Пример:
@AfterEach
Выполняется после каждого теста.
Используется для очистки ресурсов.
Пример:
@BeforeAll
Выполняется один раз перед всеми тестами в классе.
Метод должен быть static.
Пример:
@AfterAll
Выполняется один раз после всех тестов в классе.
Метод должен быть static.
Пример:
#Java #Training #Spring #Testing #JUnit_5
Структура JUnit 5
JUnit 5 (также известный как Jupiter) предоставляет богатый набор аннотаций для управления тестами. Каждая из аннотаций служит определенной цели — от настройки окружения до группировки и выполнения тестов.
Состоит из следующих модулей:
JUnit Platform: Основная платформа для запуска тестов.
JUnit Jupiter: Новый API для написания тестов.
JUnit Vintage: Обеспечивает совместимость с JUnit 4.
Аннотации для организации тестов
@Test
Используется для обозначения метода как тестового.
Этот метод должен быть public или default.
Пример:
@Test
void testAddition() {
Assertions.assertEquals(5, 2 + 3);
}
@DisplayName
Устанавливает читаемое имя для теста, которое будет отображаться в отчетах.
Пример:
@Test
@DisplayName("Тест сложения двух чисел")
void testAddition() {
Assertions.assertEquals(5, 2 + 3);
}
@Disabled
Отключает тест, чтобы он не выполнялся.
Можно указать причину отключения.
Пример:
@Test
@Disabled("Тест временно отключен из-за изменений в логике")
void testDisabled() {
Assertions.fail("Этот тест не должен выполняться");
}
Аннотации для управления жизненным циклом тестов
@BeforeEach
Выполняется перед каждым тестом.
Используется для подготовки окружения.
Пример:
@BeforeEach
void setup() {
System.out.println("Подготовка перед тестом");
}
@AfterEach
Выполняется после каждого теста.
Используется для очистки ресурсов.
Пример:
@AfterEach
void cleanup() {
System.out.println("Очистка после теста");
}
@BeforeAll
Выполняется один раз перед всеми тестами в классе.
Метод должен быть static.
Пример:
@BeforeAll
static void globalSetup() {
System.out.println("Настройка перед всеми тестами");
}
@AfterAll
Выполняется один раз после всех тестов в классе.
Метод должен быть static.
Пример:
@AfterAll
static void globalCleanup() {
System.out.println("Очистка после всех тестов");
}
#Java #Training #Spring #Testing #JUnit_5
Что выведет код?
#Tasks
public class Task261224_1 {
public static void main(String[] args) {
int x = 10;
if (x > 5) {
if (x < 15) {
System.out.println("A");
} else {
System.out.println("B");
}
} else {
System.out.println("C");
}
}
}
#Tasks
160% пьет кофе и ищет маленькую ошибку из-за которой нихера не работает😂
https://t.me/Java_for_beginner_dev
#Mems
https://t.me/Java_for_beginner_dev
#Mems
Продвинутые аннотации JUnit 5
Управление параметрами и контекстами
@Nested
Позволяет группировать связанные тесты в отдельные внутренние классы.
Пример:
@ParameterizedTest
Используется для создания параметрических тестов.
Тест выполняется несколько раз с разными значениями.
Пример:
@ValueSource
Определяет набор значений для параметрических тестов.
Пример:
@CsvSource
Передает значения в виде CSV (Comma-Separated Values).
Пример:
@EnumSource
Используется для автоматического предоставления значений из перечислений (enums) в тестовые методы.
Пример:
@CsvFileSource
Загружает данные из CSV-файла.
Пример:
Работа с условиями
@EnabledOnOs / @DisabledOnOs
Включает или отключает тест на основе операционной системы.
Пример:
@EnabledIf / @DisabledIf
Условное выполнение тестов.
Тестирование исключений и времени
@Timeout
Устанавливает максимальное время выполнения теста.
Пример:
@TestFactory
Используется для создания динамических тестов.
Пример:
#Java #Training #Spring #Testing #JUnit_5
Управление параметрами и контекстами
@Nested
Позволяет группировать связанные тесты в отдельные внутренние классы.
Пример:
@Nested
class MathTests {
@Test
void testAddition() {
Assertions.assertEquals(5, 2 + 3);
}
@Test
void testSubtraction() {
Assertions.assertEquals(1, 3 - 2);
}
}
@ParameterizedTest
Используется для создания параметрических тестов.
Тест выполняется несколько раз с разными значениями.
Пример:
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testWithParameters(int value) {
Assertions.assertTrue(value > 0);
}
@ValueSource
Определяет набор значений для параметрических тестов.
Пример:
@ParameterizedTest
@ValueSource(strings = {"Hello", "JUnit", "Test"})
void testStrings(String word) {
Assertions.assertFalse(word.isEmpty());
}
@CsvSource
Передает значения в виде CSV (Comma-Separated Values).
Пример:
@ParameterizedTest
@CsvSource({"1,2,3", "2,3,5", "3,5,8"})
void testCsvSource(int a, int b, int result) {
Assertions.assertEquals(result, a + b);
}
@EnumSource
Используется для автоматического предоставления значений из перечислений (enums) в тестовые методы.
Пример:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
@ParameterizedTest
@EnumSource(Day.class) // Все значения перечисления Day
void testWithEnumSource(Day day) {
Assertions.assertNotNull(day, "Day should not be null");
}
@CsvFileSource
Загружает данные из CSV-файла.
Пример:
@ParameterizedTest
@CsvFileSource(resources = "/data.csv", numLinesToSkip = 1)
void testCsvFileSource(int a, int b, int result) {
Assertions.assertEquals(result, a + b);
}
Работа с условиями
@EnabledOnOs / @DisabledOnOs
Включает или отключает тест на основе операционной системы.
Пример:
@Test
@EnabledOnOs(OS.WINDOWS)
void testWindowsOnly() {
Assertions.assertTrue(System.getProperty("os.name").contains("Windows"));
}
@EnabledIf / @DisabledIf
Условное выполнение тестов.
Тестирование исключений и времени
@Timeout
Устанавливает максимальное время выполнения теста.
Пример:
@Test
@Timeout(5) // Тест завершится с ошибкой, если выполнится дольше 5 секунд
void testTimeout() {
Thread.sleep(3000);
}
@TestFactory
Используется для создания динамических тестов.
Пример:
@TestFactory
Collection<DynamicTest> dynamicTests() {
return Arrays.asList(
DynamicTest.dynamicTest("1st test", () -> Assertions.assertTrue(true)),
DynamicTest.dynamicTest("2nd test", () -> Assertions.assertEquals(4, 2 * 2))
);
}
#Java #Training #Spring #Testing #JUnit_5
Введение в Mockito
Mockito – это популярная библиотека для создания mock-объектов в тестировании. Она позволяет симулировать поведение объектов, чтобы изолировать тестируемую часть кода. Важное преимущество Mockito – это интеграция со Spring, благодаря которой библиотека легко используется в проектах без дополнительной настройки. Достаточно подключить зависимость в проекте.
Основные концепции Mockito
1. Создание моков
Чтобы создать mock-объект, используется метод Mockito.mock(Class). Этот объект ведёт себя как заглушка: он не выполняет реальной логики, но может возвращать заданные вами значения.
Пример:
2. Аннотация @Mock
Аннотация @Mock упрощает создание mock-объектов. Вместо ручного вызова Mockito.mock(), вы просто добавляете эту аннотацию над полем.
Пример:
⚠️ Чтобы аннотация заработала, используйте @ExtendWith(MockitoExtension.class) (в JUnit 5) или вызовите MockitoAnnotations.openMocks(this) в JUnit 4.
Stub и возвращение значений
Stub – это настройка поведения mock-объекта. Вы указываете, какое значение должен возвращать mock при вызове его методов. В Mockito для этого используются методы when и thenReturn или thenThrow.
Пример:
Преимущества использования Mockito в Spring
Mockito прекрасно сочетается со Spring. Например:
Нет необходимости в явной настройке.
Использование моков через аннотации (@Mock, @InjectMocks) позволяет минимизировать код.
Легкая интеграция с контекстом Spring для тестирования бинов.
#Java #Training #Spring #Testing #Mockito
Mockito – это популярная библиотека для создания mock-объектов в тестировании. Она позволяет симулировать поведение объектов, чтобы изолировать тестируемую часть кода. Важное преимущество Mockito – это интеграция со Spring, благодаря которой библиотека легко используется в проектах без дополнительной настройки. Достаточно подключить зависимость в проекте.
Основные концепции Mockito
1. Создание моков
Чтобы создать mock-объект, используется метод Mockito.mock(Class). Этот объект ведёт себя как заглушка: он не выполняет реальной логики, но может возвращать заданные вами значения.
Пример:
List<String> mockList = Mockito.mock(List.class);
Mockito.when(mockList.size()).thenReturn(10);
System.out.println(mockList.size()); // Выведет: 10
2. Аннотация @Mock
Аннотация @Mock упрощает создание mock-объектов. Вместо ручного вызова Mockito.mock(), вы просто добавляете эту аннотацию над полем.
Пример:
@Mock
List<String> mockList;
⚠️ Чтобы аннотация заработала, используйте @ExtendWith(MockitoExtension.class) (в JUnit 5) или вызовите MockitoAnnotations.openMocks(this) в JUnit 4.
Stub и возвращение значений
Stub – это настройка поведения mock-объекта. Вы указываете, какое значение должен возвращать mock при вызове его методов. В Mockito для этого используются методы when и thenReturn или thenThrow.
Пример:
// Создание поведения для метода
Mockito.when(mockList.get(0)).thenReturn("Hello, Mockito!");
Mockito.when(mockList.get(1)).thenThrow(new RuntimeException("Ошибка"));
// Проверка
System.out.println(mockList.get(0)); // Выведет: Hello, Mockito!
System.out.println(mockList.get(1)); // Бросит исключение
Преимущества использования Mockito в Spring
Mockito прекрасно сочетается со Spring. Например:
Нет необходимости в явной настройке.
Использование моков через аннотации (@Mock, @InjectMocks) позволяет минимизировать код.
Легкая интеграция с контекстом Spring для тестирования бинов.
#Java #Training #Spring #Testing #Mockito
Что выведет код?
#Tasks
import java.util.stream.Stream;
public class Task271224_1 {
public static void main(String[] args) {
Stream.of(1, 2, 3, 4, 5)
.filter(n -> n % 2 == 0)
.map(n -> n * 2)
.forEach(System.out::println);
}
}
#Tasks
Проверка вызовов методов с помощью verify в Mockito
Mockito позволяет убедиться, что методы ваших mock-объектов вызывались определённое количество раз, в правильной последовательности или с определёнными параметрами. Это называется проверка взаимодействий.
Как работает verify?
Если метод не был вызван, тест упадёт с ошибкой.
Расширенные проверки
Количество вызовов:
Последовательность вызовов:
Проверка отсутствия взаимодействий:
Пример: Тестирование сервиса с использованием Mockito
Рассмотрим сервис, который взаимодействует с репозиторием:
Тест для этого сервиса:
Что мы сделали в тесте?
Создали mock для UserRepository с помощью @Mock.
Связали mock с тестируемым сервисом через @InjectMocks.
Задали поведение mock-объекта с помощью when и проверили результат.
Убедились, что репозиторий вызван с нужными параметрами через verify.
#Java #Training #Spring #Testing #Mockito #Verify
Mockito позволяет убедиться, что методы ваших mock-объектов вызывались определённое количество раз, в правильной последовательности или с определёнными параметрами. Это называется проверка взаимодействий.
Как работает verify?
List<String> mockList = Mockito.mock(List.class);
// Взаимодействие
mockList.add("Mockito");
mockList.clear();
// Проверка взаимодействий
Mockito.verify(mockList).add("Mockito"); // Проверяет вызов add с параметром "Mockito"
Mockito.verify(mockList).clear(); // Проверяет вызов clear
Если метод не был вызван, тест упадёт с ошибкой.
Расширенные проверки
Количество вызовов:
Mockito.verify(mockList, Mockito.times(1)).add("Mockito");
Mockito.verify(mockList, Mockito.never()).add("Spring");
Последовательность вызовов:
InOrder inOrder = Mockito.inOrder(mockList);
inOrder.verify(mockList).add("Mockito");
inOrder.verify(mockList).clear();
Проверка отсутствия взаимодействий:
Mockito.verifyNoInteractions(mockList);
Пример: Тестирование сервиса с использованием Mockito
Рассмотрим сервис, который взаимодействует с репозиторием:
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getUserName(Long id) {
return userRepository.findById(id).orElse("Unknown");
}
}
Тест для этого сервиса:
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void getUserName_ReturnsCorrectName() {
// Stub репозитория
Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of("John Doe"));
// Вызов метода
String result = userService.getUserName(1L);
// Проверки
Assertions.assertEquals("John Doe", result);
Mockito.verify(userRepository).findById(1L);
}
@Test
void getUserName_ReturnsUnknownForMissingUser() {
// Stub для случая, когда пользователь отсутствует
Mockito.when(userRepository.findById(2L)).thenReturn(Optional.empty());
// Вызов метода
String result = userService.getUserName(2L);
// Проверки
Assertions.assertEquals("Unknown", result);
Mockito.verify(userRepository).findById(2L);
}
}
Что мы сделали в тесте?
Создали mock для UserRepository с помощью @Mock.
Связали mock с тестируемым сервисом через @InjectMocks.
Задали поведение mock-объекта с помощью when и проверили результат.
Убедились, что репозиторий вызван с нужными параметрами через verify.
#Java #Training #Spring #Testing #Mockito #Verify