/
elendi
/
simple-crud
Обзор
Документация
Войти
/
elendi
/
simple-crud
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/test/java/com/example/crud/ProductControllerIntegrationTest.java
210 строк
9 KB
elendilearner
продукты
04 мар 2026, 07:32
04 мар 2026, 07:32
25a15ae
Код
Авторство
О чём код?
package com.example.crud; import com.example.crud.dto.ProductRequest; import com.example.crud.dto.ProductResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.*; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.Assertions.assertThat; /** * Интеграционные тесты для {@link com.example.crud.controller.ProductController}. * * <p>Поднимает полноценный Spring-контекст на случайном порту ({@code RANDOM_PORT}) * и выполняет реальные HTTP-запросы через {@link RestTemplate}, * проверяя корректность ответов для всех операций над товарами.</p> * * <p>Тесты покрывают следующие сценарии: * <ul> * <li>Получение списка всех товаров</li> * <li>Получение товара по ID</li> * <li>Получение товаров по категории</li> * <li>Поиск товаров по названию</li> * <li>Получение количества товаров</li> * <li>Создание нового товара</li> * <li>Полное обновление товара</li> * <li>Обновление цены товара</li> * <li>Удаление товара</li> * </ul> * </p> */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class ProductControllerIntegrationTest { /** * Случайный порт, на котором поднимается сервер во время теста. * Автоматически инжектируется Spring после старта контекста. */ @LocalServerPort private int port; /** * HTTP-клиент для выполнения запросов к запущенному серверу. */ private RestTemplate restTemplate; /** * Базовый URL для обращения к эндпоинтам товаров. * Формируется из {@code port} перед каждым тестом. */ private String baseUrl; /** * Инициализирует {@link RestTemplate} и формирует базовый URL перед каждым тестом. */ /** * Инициализирует {@link RestTemplate} с поддержкой метода {@code PATCH} * через Apache HttpClient и формирует базовый URL перед каждым тестом. */ @BeforeEach void setUp() { restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); baseUrl = "http://localhost:" + port + "/api/products"; } /** * Проверяет, что {@code GET /api/products} возвращает HTTP 200 * и непустой список товаров. */ @Test void getAll_shouldReturnListOfProducts() { ResponseEntity<ProductResponse[]> response = restTemplate.getForEntity(baseUrl, ProductResponse[].class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).hasSizeGreaterThan(0); } /** * Проверяет, что {@code GET /api/products/{id}} возвращает HTTP 200 * и товар с корректным {@code id}. */ @Test void getById_shouldReturnProduct() { ResponseEntity<ProductResponse> response = restTemplate.getForEntity(baseUrl + "/1", ProductResponse.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody().getId()).isEqualTo(1L); } /** * Проверяет, что {@code GET /api/products/category/{category}} возвращает HTTP 200 * и непустой список товаров, принадлежащих указанной категории. */ @Test void getByCategory_shouldReturnProductsInCategory() { ResponseEntity<ProductResponse[]> response = restTemplate.getForEntity( baseUrl + "/category/Электроника", ProductResponse[].class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).hasSizeGreaterThan(0); assertThat(response.getBody()[0].getCategory()).isEqualTo("Электроника"); } /** * Проверяет, что {@code GET /api/products/search?name=} возвращает HTTP 200 * и список товаров, в названии которых содержится указанная подстрока. */ @Test void searchByName_shouldReturnMatchingProducts() { ResponseEntity<ProductResponse[]> response = restTemplate.getForEntity( baseUrl + "/search?name=Ноутбук", ProductResponse[].class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).hasSizeGreaterThan(0); } /** * Проверяет, что {@code GET /api/products/count} возвращает HTTP 200 * и корректное количество товаров. */ @Test void count_shouldReturnProductCount() { ResponseEntity<Long> response = restTemplate.getForEntity(baseUrl + "/count", Long.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isGreaterThan(0); } /** * Проверяет, что {@code POST /api/products} возвращает HTTP 201 * и созданный товар с переданными данными. */ @Test void create_shouldReturnCreatedProduct() { ProductRequest request = new ProductRequest(); request.setName("Клавиатура Keychron"); request.setDescription("Механическая, 87 клавиш"); request.setPrice(8500.0); request.setCategory("Электроника"); ResponseEntity<ProductResponse> response = restTemplate.postForEntity(baseUrl, request, ProductResponse.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody().getName()).isEqualTo("Клавиатура Keychron"); assertThat(response.getBody().getPrice()).isEqualTo(8500.0); assertThat(response.getBody().getCategory()).isEqualTo("Электроника"); } /** * Проверяет, что {@code PUT /api/products/{id}} возвращает HTTP 200 * и товар с полностью обновлёнными данными. */ @Test void update_shouldReturnUpdatedProduct() { ProductRequest request = new ProductRequest(); request.setName("Ноутбук Dell"); request.setDescription("14 дюймов, 32 ГБ RAM"); request.setPrice(95000.0); request.setCategory("Электроника"); HttpEntity<ProductRequest> entity = new HttpEntity<>(request); ResponseEntity<ProductResponse> response = restTemplate.exchange( baseUrl + "/1", HttpMethod.PUT, entity, ProductResponse.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody().getName()).isEqualTo("Ноутбук Dell"); assertThat(response.getBody().getPrice()).isEqualTo(95000.0); } /** * Проверяет, что {@code PATCH /api/products/{id}/price} возвращает HTTP 200 * и товар с обновлённой ценой. */ @Test void updatePrice_shouldReturnProductWithNewPrice() { ResponseEntity<ProductResponse> response = restTemplate.exchange( baseUrl + "/1/price?price=69999.0", HttpMethod.PATCH, null, ProductResponse.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody().getPrice()).isEqualTo(69999.0); } /** * Проверяет, что {@code DELETE /api/products/{id}} возвращает HTTP 204 No Content. */ @Test void delete_shouldReturnNoContent() { ResponseEntity<Void> response = restTemplate.exchange( baseUrl + "/1", HttpMethod.DELETE, null, Void.class ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } }