Middle
124
questionbank
Какие тесты вы пишете и каким образом?
Ответ от нейросети
sobes.tech AI
Пишу следующие виды тестов:
- Unit-тесты: Тестируют отдельные компоненты или методы класса изолированно от остальной системы. Использую JUnit или TestNG. Для мокирования зависимостей — Mockito.
- Integration-тесты: Тестируют взаимодействие между несколькими компонентами, подсистемами или сервисами. Например, взаимодействие с базой данных или внешним API. Использую Spring Boot Test для тестирования Spring-приложений, Testcontainers для тестирования с реальными зависимостями (базы данных, месседж-брокеры).
- Component-тесты / End-to-End (E2E) тесты: Тестируют систему с точки зрения пользователя от начала до конца. Чаще всего автоматизированные тесты пользовательского интерфейса или API. Для API использую Rest-Assured. Для UI — Selenium (хотя предпочитаю писать API-тесты, так как они более стабильны и быстрее).
Процесс написания тестов:
- Выбор фреймворка: JUnit 5 или TestNG для unit-тестов, Spring Boot Test, Rest-Assured, Testcontainers для интеграционных и компонентных тестов.
- Написание тестов до или в процессе написания кода: Использую TDD (Test-Driven Development) или пишу тесты сразу после написания функциональности.
- Изоляция тестов: Для unit-тестов использую Mockito для мокирования зависимостей, чтобы тестировать только изолированный компонент.
- Структура теста: Обычно придерживаюсь структуры Arrange-Act-Assert (Подготовка данных, Выполнение действия, Проверка результата).
- Четкое именование тестов: Названия тестов должны ясно описывать, что именно тестируется и при каких условиях. Например,
userService_createUser_shouldSaveUserInDatabase. - Тестирование граничных условий и ошибок: Проверяю как нормальные сценарии, так и случаи с некорректными входными данными, исключениями и граничными значениями.
- Рефакторинг тестов: Поддерживаю тесты в чистоте и читаемости так же, как и основной код.
Пример unit-теста с Mockito и JUnit 5:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock // Зависимость, которую мы мокируем
private UserRepository userRepository;
@InjectMocks // Сервис, который мы тестируем
private UserService userService;
@Test
void createUser_shouldSaveUserInDatabase() {
// Arrange: Подготовка данных и мокирование поведения
User user = new User("Alice", "alice@example.com");
when(userRepository.save(any(User.class))).thenReturn(user); // Мокируем метод save репозитория
// Act: Выполнение действия, которое мы тестируем
User createdUser = userService.createUser(user);
// Assert: Проверка результата
assertEquals("Alice", createdUser.getName()); // Проверяем, что пользователь создан с правильным именем
verify(userRepository, times(1)).save(any(User.class)); // Проверяем, что метод save был вызван ровно 1 раз
}
}
Пример использования Rest-Assured для интеграционного теста API:
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
class UserControllerIntegrationTest {
@BeforeAll
static void setup() {
// Настройка базового URL для тестов
RestAssured.baseURI = "http://localhost:8080";
RestAssured.port = 8080;
}
@Test
void getUserById_shouldReturnUser() {
// Act & Assert: Выполнение запроса и проверка ответа
given()
.when()
.get("/users/1") // URL для получения пользователя по ID
.then()
.statusCode(200) // Проверка статуса ответа (OK)
.body("name", equalTo("John Doe")); // Проверка значения поля в теле ответа
}
}