Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Интеграционное тестирование
Интеграционное тестирование (integration testing) — это тестирование взаимодействия между несколькими компонентами системы или между системой и внешними сервисами. Это уровень тестирования, который находится между модульным (unit) и системным (end-to-end) тестированием.
Пирамида тестирования
E2E Tests (5-10%)
System Tests (15-20%)
Integration Tests (20-30%)
Unit Tests (50-60%)
Интеграционные тесты проверяют, как разные части системы работают вместе.
Различие: Unit vs Integration vs E2E
Unit Test — тестирует один метод/класс изолированно:
@Test
public void testAddUser() {
UserService service = new UserService(mock(UserRepository.class));
User user = service.createUser("test@test.com", "password");
assertEquals("test@test.com", user.getEmail());
}
Integration Test — тестирует несколько компонентов вместе:
@SpringBootTest
@AutoConfigureMockMvc
public class UserIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private UserRepository userRepository;
@Test
public void testCreateUserEndToEndFlow() throws Exception {
// 1. Отправить HTTP запрос
// 2. Контроллер вызовет Service
// 3. Service вызовет Repository
// 4. Repository сохранит в базу
// 5. Проверить, что всё прошло успешно
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"email\":\"test@test.com\"}")
).andExpect(status().isCreated());
// Проверить, что пользователь действительно сохранён в БД
User user = userRepository.findByEmail("test@test.com");
assertNotNull(user);
}
}
E2E Test — тестирует через UI (Playwright, Selenium):
test('Create user through web UI', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.fill('input[name="email"]', 'test@test.com');
await page.click('button[type="submit"]');
await expect(page).toHaveURL('http://localhost:3000/users/success');
});
Типы интеграционного тестирования
1. API Integration Testing
Тестирование контроллеров и их взаимодействия с сервисами:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserApiIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private UserService userService;
@Test
public void testGetUserByIdApi() {
// Подготовка: создать пользователя через сервис
User savedUser = userService.createUser("John", "john@example.com");
// Тест: получить через API
ResponseEntity<User> response = restTemplate.getForEntity(
"/api/users/" + savedUser.getId(),
User.class
);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals("John", response.getBody().getName());
}
}
2. Database Integration Testing
Тестирование взаимодействия между приложением и БД:
@DataJpaTest
public class UserRepositoryIntegrationTest {
@Autowired
private UserRepository userRepository;
@Test
public void testSaveAndRetrieveUser() {
// Сохранить в реальную БД
User user = new User();
user.setName("Alice");
user.setEmail("alice@example.com");
userRepository.save(user);
// Получить из БД и проверить
User retrieved = userRepository.findByEmail("alice@example.com");
assertNotNull(retrieved);
assertEquals("Alice", retrieved.getName());
}
}
3. External Service Integration Testing
Тестирование взаимодействия с внешними API:
@Test
public void testPaymentGatewayIntegration() throws Exception {
// Используем VCR.py или MockWebServer для записи HTTP ответов
PaymentService paymentService = new PaymentService(httpClient);
PaymentResponse response = paymentService.processPayment(
new PaymentRequest(100.0, "USD")
);
assertEquals("SUCCESS", response.getStatus());
assertNotNull(response.getTransactionId());
}
С использованием MockWebServer:
@Test
public void testExternalApiIntegration() throws Exception {
MockWebServer mockWebServer = new MockWebServer();
mockWebServer.enqueue(new MockResponse()
.setBody("{\"status\":\"success\"}")
.addHeader("Content-Type", "application/json")
);
mockWebServer.start();
ExternalService service = new ExternalService(
mockWebServer.url("/").toString()
);
ApiResponse response = service.callApi();
assertEquals("success", response.getStatus());
mockWebServer.shutdown();
}
4. Cache Integration Testing
Тестирование взаимодействия с кешем:
@SpringBootTest
@EnableCaching
public class CacheIntegrationTest {
@Autowired
private UserService userService;
@Autowired
private CacheManager cacheManager;
@Test
public void testUserCaching() {
// Первый вызов — идёт в БД
User user1 = userService.getUserById(1L);
// Второй вызов — из кеша
User user2 = userService.getUserById(1L);
// Проверить, что данные в кеше
Cache cache = cacheManager.getCache("users");
assertNotNull(cache.get(1L));
// Очистить кеш
cache.clear();
assertNull(cache.get(1L));
}
}
Инструменты интеграционного тестирования
1. Spring Boot Test
@SpringBootTest
@AutoConfigureMockMvc
public class IntegrationTest { }
2. MockMvc для тестирования контроллеров
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
).andExpect(status().isCreated());
3. TestRestTemplate для REST API
ResponseEntity<User> response = restTemplate.getForEntity(
"/api/users/1", User.class
);
4. TestContainers для реальных зависимостей (БД, Kafka)
@Testcontainers
public class DockerIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>()
.withDatabaseName("testdb")
.withUsername("user")
.withPassword("password");
@Test
public void testWithRealDatabase() {
// Тест использует реальную БД в Docker контейнере
userRepository.save(new User("Alice"));
User found = userRepository.findByName("Alice");
assertNotNull(found);
}
}
5. WireMock для мокирования внешних сервисов
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
public class ExternalServiceIntegrationTest {
@Test
public void testExternalServiceCall() {
stubFor(get(urlEqualTo("/api/external"))
.willReturn(aResponse()
.withStatus(200)
.withBody("{\"result\":\"mocked\"}"))
);
ApiResponse response = externalService.callApi();
assertEquals("mocked", response.getResult());
}
}
Особенности интеграционных тестов
Плюсы:
- Тестируют реальное взаимодействие компонентов
- Ловят проблемы, которые unit тесты пропустят
- Проверяют конкретные бизнес-сценарии
- Дают уверенность в качестве
Минусы:
- Медленнее, чем unit тесты (требуют реальной БД, HTTP запросов)
- Более сложные в настройке
- Требуют больше ресурсов
- Может быть нестабильны (если внешние сервисы недоступны)
Лучшие практики
-
Изолируй внешние зависимости
- Используй MockWebServer вместо реальных API
- Используй TestContainers для БД
-
Используй фикстуры для подготовки данных
@Before public void setUp() { User testUser = new User("Test", "test@example.com"); userRepository.save(testUser); } -
Тестируй happy path и error cases
@Test public void testSuccessfulPayment() { } @Test public void testPaymentFailure() { } -
Переиспользуй тестовые контексты
@SpringBootTest public class BaseIntegrationTest { } -
Группируй интеграционные тесты отдельно
@Tag("integration") public class UserIntegrationTest { }
Интеграционное тестирование — это критичный уровень тестирования, который гарантирует, что компоненты работают вместе корректно и приложение выполняет свои бизнес-функции.